Skip to content Skip to sidebar Skip to footer

Updating A Page At Refresh AND Change Of State

I'm trying to build a todo page where I can input todos in my input field. All todos will be rendered below. I managed to build a form where I can type in a todo title and send it

Solution 1:

You can either update the state or sync up with database by sending another GET. Let me break it down into 2 solutions:

  • Just update the state
  • Make a GET request after the POST request and update the state

Just update the state

// you code ...
handleSubmit(event){
  event.preventDefault()
  const newTodo = { title: this.state.title };                // extract your todo into const

  axios({
      method: "POST",
      url: `${process.env.REACT_APP_API_BASE}/todo`,
      data: qs.stringify(newTodo),                         // send todo in the POST
      headers: {"content-type": "application/x-www-form-urlencoded"},
      withCredentials: true
  })
  .then((response) => {
      console.log(response)
      this.setState(prevState => ({                        // immutably update the state
        todos: [...prevState.todos, newTodo]
      }));
  })
  .catch((error) => {
      console.log(error.response)
  })
}
// your code ...

Send GET after POST:

// your Todo component
class Todo extends React.Component {
  constructor() {
    super();

    this.state = {
      title: "",
      todos: [],
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  // extract method for loading TODOs (your previous componentDidMount)
  loadTodos = () => {
    axios({
      method: "GET",
      url: `${process.env.REACT_APP_API_BASE}/todo`,
      withCredentials: true,
    })
      .then((response) => {
        console.log(response);
        let todolist = response.data;
        this.setState({ todos: todolist });
      })
      .catch((error) => {
        console.log(
          "You've made an error when getting the todos charles: ",
          error
        );
      });
  }

  componentDidMount() {
    this.loadTodos();                                 // use the extracted method
  }

  handleChange(event) {
    event.preventDefault();
    let name = event.target.name;
    let value = event.target.value;
    this.setState({
      [name]: value,
    });
    console.log(this.state.title);
  }

  handleSubmit(event) {
    event.preventDefault();
    if (!this.state.title) {
      debugger;
    }
    axios({
      method: "POST",
      url: `${process.env.REACT_APP_API_BASE}/todo`,
      data: qs.stringify({ title: this.state.title }),
      headers: { "content-type": "application/x-www-form-urlencoded" },
      withCredentials: true,
    })
      .then((response) => {
        console.log(response);
        this.loadTodos();                            // use the extracted method
      })
      .catch((error) => {
        console.log(error.response);
      });
  }

  handleDelete(todoId) {
    axios
      .delete(`${process.env.REACT_APP_API_BASE}/todo/${todoId}`)
      .then((response) => {
        const remainingTodos = this.state.todos.filter(
          (element) => element._id !== todoId
        );
        this.setState({
          todos: remainingTodos,
        });
      })
      .catch((err) => console.log(err));
  }

  render() {
    return (
      <div>
        <DefaultLayout>
          <h1>To-do things for this app</h1>
          <h2 className="todotitle">Add your to-do here, Charles!</h2>
          <form className="todocontainer" onClick={this.handleSubmit}>
            <div className="inputbuttonandfield">
              <div className="inputcontainer">
                <div className="captionpart">
                  <label className="captionlabel" htmlFor="title">
                    Add to-do:
                  </label>
                  <br></br>
                  <input
                    className="captionform"
                    type="text"
                    name="title"
                    value={this.state.title}
                    placeholder="Type your to-do here!"
                    onChange={(e) => this.handleChange(e)}
                  ></input>
                  <button className="shootbutton">Add!</button>
                </div>
              </div>
            </div>
          </form>

          {this.state.todos.map((element) => (
            <div className="todosoverviewlister" key={element._id}>
              <Todoitem id={element._id} title={element.title} />

              <button
                className="tododelete"
                onClick={() => this.handleDelete(element._id)}
              >
                Delete
              </button>
            </div>
          ))}
        </DefaultLayout>
      </div>
    );
  }
}

export default Todo;

Solution 2:

I believe the issue is that you're not updating the state when you submit (during the add operation). In your delete, you correctly keep the list in state synced with the list on the server by removing the element locally as well. In the add, you should to something similar by adding the new element to the list in state (or more precisely, make a deep copy and overwrite the one in state). That should do it.

There is no need to refetch the entire list from the server unless there are multiple users operating on the same list. If that's the case, you can add a get() call in the response of your submit. As long as the response of that operation writes to state, it will update correctly. But again, avoid that unless you need it as it will make your app slower and less responsive.


Post a Comment for "Updating A Page At Refresh AND Change Of State"