最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin3浏览0评论

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 ponent 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 ponentDidMount so I'm including that in case it helps.

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

     ponentDidMount() {
          // 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=".6.3/umd/react.production.min.js"></script>
<script src=".6.3/umd/react-dom.production.min.js"></script>

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 ponent 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 ponentDidMount so I'm including that in case it helps.

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

     ponentDidMount() {
          // 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./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./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.

Share Improve this question asked Sep 10, 2019 at 14:20 Jacob BroughtonJacob Broughton 4222 gold badges6 silver badges16 bronze badges 2
  • Are you sure about class ponent? I would suggest to start smoothly moving to functional ponents and hooks. – Pencroff Commented Jul 5, 2021 at 11:09
  • This was a while ago, i use hooks / functional ponents now – Jacob Broughton Commented Jul 5, 2021 at 14:28
Add a ment  | 

3 Answers 3

Reset to default 0

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 ponent.

you've to update your state, and once you'll update the state your ponent 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. i.e:

  // 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:

ponentDidMount() {
    this.getTodos();
}

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

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

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

Methode 2:

ponentDidMount() {
    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});
}
发布评论

评论列表(0)

  1. 暂无评论