【问题标题】:React not re-rendering on state change with useState使用 useState 响应不重新渲染状态更改
【发布时间】:2020-06-13 13:09:23
【问题描述】:

我正在尝试创建一个测验制作应用程序,用户可以在其中向动态表单添加多个问题。在此表单中,用户可以根据需要添加或删除问题组件。当用户单击新问题处理程序 (handleNewQuestion) 时,一个新问题将连接到组件状态下的 questions 数组中。

const handleNewQuestion = () => {
      setQuestions([
         ...questions,
         <Question
            key={questions.length}
            count={questions.length}
            formData={formData}
            setFormData={setFormData}
            handleRemoveQuestion={handleRemoveQuestion}
         />
      ])
   }

<Button onClick={handleNewQuestion} variant="outline-primary">
    New Question
</Button>

我遇到的问题是,每当我尝试使用删除问题处理程序 (handleRemoveQuestion) 删除问题时,它总是会删除错误的问题。当试图解决这个问题时,我在控制台中记录了问题数组,发现新问题不在数组中,而且根据我点击的问题组件,我得到不同的结果。您可以在提供的图像中看到我得到的结果。

quiz form with 2 questions

基本上发生的事情是,根据我尝试删除的问题组件,控制台会显示不同状态的问题数组。例如,当我尝试删除第一个问题组件时,我得到一个空数组,当我单击第二个问题组件时,我得到一个包含一个元素的数组。即使呈现了多个问题,如果我尝试删除第一个问题,我仍然会得到一个空数组。

我不知道为什么会发生这种情况,如果有人能解释这里发生了什么,我将不胜感激。

干杯!

【问题讨论】:

  • setQuestions 的调用肯定会触发重新渲染。请使用 minimal reproducible example 来更新您的问题,以展示问题,最好是使用 Stack Snippets([&lt;&gt;] 工具栏按钮)的 runnable 问题。 Stack Snippets 支持 React,包括 JSX; here's how to do one.
  • “每当我尝试使用删除问题处理程序 (handleRemoveQuestion) 删除问题时,它总是会删除错误的问题” - 您只显示添加新问题而不显示您遇到问题的代码与。
  • 删除问题处理程序目前只记录问题数组,我认为没有必要包含它。对不起,我应该更具体。
  • 链接的图片并没有真正提供太多信息。 handleRemoveQuestion 似乎正在使用一些需要修复的逻辑,因为它为不同的问题记录了不同的内容。

标签: javascript reactjs state react-hooks virtual-dom


【解决方案1】:

如果您正在修改数组(以任何方式而不是添加到数组中),则不能使用 key。来自the documentation

如果项目的顺序可能发生变化,我们不建议对键使用索引。这可能会对性能产生负面影响并可能导致组件状态出现问题。查看 Robin Pokorny 的文章以获取 in-depth explanation on the negative impacts of using an index as a key

(我的重点)

另外,请注意,您对setQuestions 的调用不会更新count 的现有问题,这似乎是个问题。

为您的问题分配唯一 ID,并在删除问题时使用这些 ID。如果问题本质上没有唯一 ID,您可以给他们一个的一种方法是使用组件外部的变量来提供“下一个”要使用的 ID:

let nextQuestionId = 1;

const YourComponent = props => {
    // ...
    const handleNewQuestion = () => {
      setQuestions([
         ...questions,
         <Question
            key={nextQuestionId++}
            count={questions.length}
            formData={formData}
            setFormData={setFormData}
            handleRemoveQuestion={handleRemoveQuestion}
         />
      ]);
   };

   const removeQuestion = id => {
       setQuestions(questions.filter(q => q.id !== id));
   };
};

该示例没有处理count 问题。如果问题确实需要计算,您必须在添加/删除时重新创建所有问题。我将把它作为练习留给读者,希望您在Question 上并不真的需要count...

【讨论】:

    猜你喜欢
    • 2020-06-25
    • 2022-01-17
    • 2019-06-26
    • 2022-11-06
    • 1970-01-01
    • 2021-12-18
    • 2019-10-06
    • 2018-02-27
    • 1970-01-01
    相关资源
    最近更新 更多