【问题标题】:How to re-render component after fetch request and state change?获取请求和状态更改后如何重新渲染组件?
【发布时间】:2020-01-12 07:56:09
【问题描述】:

我刚开始在后端做出反应和绑定,但在我发出提取请求后,我必须重新加载页面才能看到任何更改。一旦调用函数,数据库就会更新,但组件不会重新呈现。我知道 setState 是异步工作的,所以我尝试在 setState 的回调中调用我的函数,但这不起作用。

这发生在我的 handleSubmithandleDelete 函数上。我的初始获取请求在我的 componentDidMount 中,因此我将其包括在内以防万一。

我在网站上找不到我需要的答案,也许建议刚刚关闭,但我在这里,哈哈。提前致谢。

     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>

我正在寻找的结果是,一旦我添加了一个待办事项,它就会立即呈现在我的列表中,而不是仅在页面重新加载时呈现。

【问题讨论】:

  • 你确定类组件吗?我建议开始顺利地转向功能组件和钩子。
  • 这是前段时间,我现在使用钩子/功能组件

标签: javascript node.js reactjs mongodb fetch


【解决方案1】:

在请求中从后端返回详细信息,使用该值更新状态,

目前您只是在后端执行操作,前端不知道它发生在后端。 最好的方法是在对数据库执行操作后将完整数据(列表或对象)传递回前端,并将值链接到状态, 如果数据是批量数据,则从后端发送成功消息(200 就足够了)到前端,如果成功更改前端的值(列表), 将值(列表)链接到前端的状态以重新渲染组件。

【讨论】:

    【解决方案2】:

    您必须更新您的状态,一旦您更新状态,您的组件将重新渲染,并显示最新的更改。 在这里我假设你在你的状态中设置的“todos”是一个数组,然后在删除和添加时更新它。 即:

      // 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})
          })
         };
    

    【讨论】:

    • 嘿伙计,这个解决方案几乎工作得很好。不过有一件事,一旦我删除,我猜它会将 uniqueId 返回为空?一旦我删除所有内容并添加新任务并尝试删除,我得到一个 404,这告诉我 fetch 正在请求“/api/todos/null”路由,其中​​ uniqueId 应该代替 null。
    • 我的错,实际上似乎是handleSubmit的问题。看起来数据是作为 todos 状态对象发送的,而不是可以正确放入 currentTodos 数组的索引。例如,数据返回“1: {todos: Array(1), task: "asdf", from: "asdf"}" .....虽然它应该看起来像 "{_id: "5d77c380e7cc95407482d79a", task: "asdf", from: "asdf", __v: 0}"....对于冗长杂乱的回复感到抱歉。在我看来,它只是从状态中提取而不是与数据库交互,只是说缺少“__v”和“_id”。
    • 那么你的问题解决了吗?还是仍然存在?
    • 问题依然存在,添加或删除任务通常需要点击2次按钮。也不一致,因为它只有 50% 的时间这样做。数据库每次都正确更新,它只是我所看到的前端。
    【解决方案3】:

    您可能没有更改状态“待办事项”,这就是它不渲染的原因。您可以在每次更改后(在删除、更新、添加...之后)获取 todos 或自己更改状态。

    方法一:

    componentDidMount() {
        this.getTodos();
    }
    
    getTodos = () => {
        //fetch todos, setState
    }
    
    handleSubmit = () => {
        fetch(...).then(this.getTodos);
    }
    
    handleDelete = () => {
        fetch(...).then(this.getTodos);
    }
    

    方法二:

    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});
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-20
      • 2019-06-29
      • 1970-01-01
      • 2019-10-06
      • 2017-03-24
      • 2020-04-07
      • 2021-11-15
      相关资源
      最近更新 更多