Реагируйте не на повторный рендеринг при изменении состояния с помощью useState - PullRequest
0 голосов
/ 29 февраля 2020

Я пытаюсь создать приложение для создания тестов, в котором пользователь может добавить несколько вопросов в динамическую форму c. В этой форме есть компоненты вопросов, которые пользователь может добавлять или удалять по своему усмотрению. Когда пользователь щелкает новый обработчик вопроса (handleNewQuestion), новый вопрос присоединяется к массиву вопросов в состоянии компонента.

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) всегда удаляет неправильный вопрос. Пытаясь решить эту проблему, я консоль зарегистрировал массив вопросов в состоянии и обнаружил, что новых вопросов не было в массиве, а также я получаю разные результаты в зависимости от того, на какой компонент вопроса я нажимаю. Вы можете увидеть результаты, которые я получаю на предоставленном изображении.

Форма для викторины с 2 вопросами

По сути, происходит то, что в зависимости от того, какой компонент вопроса я пытаюсь удалить консоль показывает массив вопросов в разных состояниях. Например, когда я пытаюсь удалить первый компонент вопроса, я получаю пустой массив, а когда я щелкаю второй компонент вопроса, я получаю массив с одним элементом. Даже если будет задано несколько вопросов, если я попытаюсь удалить первый вопрос, я все равно получу пустой массив.

Я понятия не имею, почему это происходит, и я был бы очень признателен, если бы кто-то мог объяснить, что здесь происходит .

ура!

1 Ответ

2 голосов
/ 29 февраля 2020

Вы не можете использовать это key, если вы изменяете массив (иначе, чем просто добавляете его). Из документации :

Мы не рекомендуем использовать индексы для ключей, если порядок элементов может измениться. Это может отрицательно повлиять на производительность и может вызвать проблемы с состоянием компонента . Ознакомьтесь с статьей Робина Покорного, в которой содержится подробное объяснение негативных последствий использования индекса в качестве ключа .

(мой акцент)

Также обратите внимание, что в вашем звонке на setQuestions ничего не будет обновляться count по существующим вопросам, что кажется проблемой.

Назначьте вашим вопросам уникальные идентификаторы и используйте эти идентификаторы при снятии вопросов. Если вопросы по сути не имеют уникального идентификатора, один из способов, которым вы можете их задать, - это использовать переменную вне компонента, которая дает «следующий» идентификатор для использования:

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. Если вопросы действительно должны иметь количество, вам придется заново создать все вопросов при добавлении / удалении. Я оставлю это как упражнение для читателя в надежде, что вам все равно не нужно count на Question в любом случае ...

...