简体   繁体   中英

How to re-render component after fetch request and state change?

I'm new to react and tying in the back end but after I make the fetch requests, I have to reload the page to see any changes. The database is updated as soon as the functions are called but the component doesn't re-render. I know setState works asynchronously, so I tried calling my functions in the callback of setState but that did not work.

This happens on both my handleSubmit and handleDelete functions. My initial get request is in my componentDidMount so I'm including that in case it helps.

I couldn't find the answer that I needed on the site, maybe the recommendations were just off but here I am, lol. Thanks in advance.

 componentDidMount() { // todos is the data we get back // setting the state to newly aquired data fetch("/api/todos")`enter code here`.then(res => res.json()).then(todos => this.setState({ todos }, () => console.log("Todos fetched...", todos))).catch(err => console.log(err)) } // onClick for submit button handleSubmit = (e) => { e.preventDefault(); const data = this.state; fetch("/api/todos", { method: "post", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) }; // onClick for delete button handleDelete = (e) => { e.preventDefault(); let uniqueId = e.target.getAttribute("id") fetch(`/api/todos/${uniqueId}`, { method: "delete", headers: { 'Content-Type': 'application/json' } }) }; // Some of the JSX if needed <DeleteBtn id={todo._id} onClick={this.handleDelete} >X</DeleteBtn> <Form onSubmit={this.handleSubmit} id="myForm"></Form>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

The result I'm looking for is once I add a todo, for it to render on my list immediately, rather than only upon page reload.

Return the details from the back-end in the requests, use that values to update the state,

Currently you just perform the operation on the back-end and front-end doesn't know that it happened in the back-end. The Best way is to either pass the full data(list or object) back to front-end after operation performed on the DB and link the values to a state, if the data is bulk then send a success message(200 is enough) back from back-end to front-end and if success change the value(list) in front-end, Link the value(list) to a state in front-end to have a re rendering of the component.

you've to update your state, and once you'll update the state your component will re-render and it'll shows the latest changes. Here i am assuming "todos" you've set in your state is an array, then just update it on deleting and adding. ie:

  // onClick for submit button
    handleSubmit = (e) => {
        e.preventDefault();
        const data = this.state;
        const currentTodos = [...this.state.todos]
        fetch("/api/todos", {
            method: "post",
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data)
        }).then(()=>{
           currentTodos.push(data);
           this.setState({todos:currentTodos})
        })
    };
 // similarly for delete you can do

 // onClick for delete button
     handleDelete = (e) => {
        e.preventDefault();
        let uniqueId = e.target.getAttribute("id")
        let currentTodos = [...this.state.todos];
        fetch(`/api/todos/${uniqueId}`, {
            method: "delete",
            headers: { 'Content-Type': 'application/json' }
        }).then(()=>{
         let updatedTodos = currentTodos.filter(todo=>todo._id !==uniqueId);
         this.setState({todos:updatedTodos})
      })
     };

You are probably not changing your state "todos" that is why it doesn't render. You could fetch todos after every change (after remove, update, add...) or change the state yourself.

Methode 1:

componentDidMount() {
    this.getTodos();
}

getTodos = () => {
    //fetch todos, setState
}

handleSubmit = () => {
    fetch(...).then(this.getTodos);
}

handleDelete = () => {
    fetch(...).then(this.getTodos);
}

Methode 2:

componentDidMount() {
    this.getTodos();
}

getTodos = () => {
    //fetch todos, setState
}

handleSubmit = () => {
    fetch(...);
    let todos = this.state.todos;
    todos.push(newTodo);
    this.setState({todos});
}

handleDelete = () => {
    fetch(...);
    let todos = this.state.todos;
    //remove todo from todos
    this.setState({todos});
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM