【问题标题】:ReactJS - useState updates value in top-level component but component doesn't re-renderReactJS - useState 更新顶级组件中的值,但组件不会重新渲染
【发布时间】:2021-10-10 19:13:22
【问题描述】:

所以我有一个组件,它传入了一个由 useState 管理的“posts”变量,在我的 App 组件中,我有一些使用该变量的子组件:

function App() {

    const [posts, updatePosts] = useState([
        {
            title: "Cut the Grass",
            description: "Get it done before 4pm",
        },
        {
            title: "Purchase LOTR: DVD box set",
            description: "Extended Edition."
        }
    ])

    return (
        <div>
            <UserBar loggedInFlag = {userIsLoggedIn}/>
            <br /><br /><hr /><br />

            <CreateTodo todoList={posts} updatePosts = { () => updatePosts } />
            <input type="submit" value="test" onClick={() => console.log(posts)}/>
            <TodoList items={posts}/>

        </div>
    )
}
export default App;

在我的 CreateTodo 组件中有一个逻辑可以抓取新帖子的字段,将其添加到 posts 数组,并成功更新 posts 变量;我可以使用第二行上的“测试”按钮来测试它,它总是将正确的待办事项列表打印到控制台,并且它包含我的新帖子。所以这向我表明&lt;CreateTodo&gt; 内的posts 的更新可以很好地上升到我的App 组件。

但是,&lt;TodoList &gt; 组件使用与上述相同的 posts 变量,在更新变量时不会重新渲染。当我在 IDE 中更改一些代码,保存,然后页面刷新为新列表时,该组件仅显示 todolist(具有新值)。 如何修复我的 useState 以便每当 post 值更新时,它会自动重新呈现 &lt;TodoList &gt; 组件?

作为参考,这是该组件的外观。

export default function TodoList({ items}) {
    
    return (
        <div>
            {items.map( (todo, i) => <Todo {...todo} title={todo.title} description={todo.description} key={'post-' + i} />)}
        </div> 
    )

下面是 CreateTodo 组件的外观:

import React from 'react'

export default function CreateTodo ({todoList, updatePosts}) {
     return (
          <form onSubmit={e => e.preventDefault()} style={{borderStyle:"solid"}}>

             <div>
                 <br/>
                 <label htmlFor="create-title">Title:</label>
                 <br/>
                 <input type="text" id="create-title" />

                 <br/>
                 <label htmlFor="create-title">Description (optional):</label>
                 <br/>
                 <input type="text" id="create-description" />
                 <br/>

                 <br/>
             </div>

             <input type="submit" value="Create" onClick={() => addTodo({todoList, updatePosts})}/>
         </form>   
          )
 }
 

 function addTodo({todoList, updatePosts}){
    let newTodo = {
        title : document.getElementById("create-title").value,
        description : document.getElementById("create-description").value,
        dateCreated : Date.now(),
        completed : false,
        dateCompleted : null
    }

    todoList.push(newTodo);
    updatePosts(todoList);

    document.getElementById("create-title").value = "";
    document.getElementById("create-description").value = "";

    // alert(`"${newTodo.title}" has been added to list`);
 }

【问题讨论】:

  • 你能分享CreateTodo组件的内容,看看你是如何更新帖子的吗?
  • @CertainPerformance 是的,正如我提到的,传递给 的 updatePosts 在该组件内被调用。我将更新问题以包含该组件中的代码以获得更多背景
  • @Alimo 已更新,希望对您有所帮助

标签: reactjs react-hooks state use-state


【解决方案1】:

首先,您需要将updatePosts 函数直接传递给您的组件:

<CreateTodo todoList={posts} updatePosts={updatePosts} />

其次,在您的 addTodo 函数中,您正在直接改变状态对象:

// Don't do this
todoList.push(newTodo);

您需要做的就是使用更新后的列表致电updatePosts

updatePosts([
  ...todoList,
  newTodo,
]);

【讨论】:

  • 谢谢,看来这行得通。你能解释一下为什么updatePosts(todoList); 不起作用但你的方法可以吗?这是让我困惑的部分
  • 你不应该直接改变状态对象。您使用.push 方法完成的。因为 React 需要知道您何时更新状态以重新渲染组件。这就是为什么您需要使用提供的updatePosts 函数并将新状态作为参数传递的原因。在这种情况下,新状态是包含旧列表和新成员的新列表。
【解决方案2】:

需要在 updatePosts 属性中添加 ()

updatePosts={() => updatePosts()} 或者只是 updatePosts={updatePosts}

【讨论】:

    猜你喜欢
    • 2020-10-11
    • 2021-08-04
    • 2018-09-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 2021-12-06
    相关资源
    最近更新 更多