Как сделать обновление состояния, когда обновляется только массив строк - PullRequest
1 голос
/ 28 июня 2019

Ребята, у меня есть этот пример кода ниже:

const [data, setData] = useState([{question: '', option: ['']}]);

Тогда данные и setData будут переданы моему компоненту, как:

<Question setData={setData} data={data}/>

Мой код внутри компонента Question:

const handleAddOption = (questionIndex: number) => {
    let newArray = data;

    newArray.map((item: any, i: number) => {
      if (i === questionIndex) {
        newArray[questionIndex].options.push('');
      }
    });

    setData(newArray);
  };

Проблема в том, что, если я добавлю новый объект целиком, он «обновит» мою страницу и покажет, но, когда я добавлю, как последние строкикод, только новая строка внутри массива, он не будет «перерисовывать».

Кто-нибудь знает, как решить эту проблему?

Ответы [ 3 ]

0 голосов
/ 29 июня 2019

Грубая реализация


Я думаю, вы можете изменить:

const [data, setData] = useState([{question: '', option: ['']}]);

// into

const [questions, setQuestions] = useState([]);

И, как вы получаете новые объекты вопросов, вы можете сделать setQuestions([...questions, newQuestion]).

То есть при условии, что у вас есть форма, которая получает данные для новых вопросов. Если это так, в вашей функции onSubmit для вашей формы вы можете сгенерировать новый объект вопроса и затем выполнить setQuestions([...questions, newQuestion]).

0 голосов
/ 30 июня 2019

В действии первое правило: , не изменяйте состояние напрямую .Он работает для компонентов на основе классов и setState, работает для редукторов redux, работает и для useState на основе хуков.

Вам необходимо

setData((data) => data.map((item, index) => {
  if (index !== questionIndex) return item;
  return {
     ...item,
     options: [
        ...item.options,
        ''
     ]
  };
}));

Здесь нужно выделить несколько пунктов:

  1. , а также для setState компонента на основе класса, есть возможность обеспечить обратный вызов в функцию обновления.Я бы лучше пропустил подробное описание здесь.Может предложить взглянуть на SO вопрос и ReactJS docs .Да, речь идет не о хуках, но использует ту же логику.

  2. Нам нужно объединить наши старые данные с изменениями, чтобы свойства, которые мы не хотим изменять, оставались неизменными.Вот и весь этот оператор спреда так редко используется.Взгляните на статью об обработке массивов в состоянии для React

  3. И последнее, но не менее важное: мы должны проверить, чтобы напрямую вернуть item, если мы не хотимобновить без каких-либо изменений.Это дает нам уверенность в том, что никакие связанные дочерние компоненты не будут повторно отображаться с фактически одинаковыми данными.Вы можете найти дополнительную информацию, выполнив поиск по запросу "ссылочное равенство" (здесь вы можете найти одну из статей ).

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

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

0 голосов
/ 29 июня 2019
  1. Похоже, у вас есть опечатка newArray[questionIndex].option.push(''); вместо newArray[questionIndex].options.push('');
  2. Но если это не поможет, попробуйте forceUpdate(); больше деталей. Вы можете найти в этом ответе Как заставить компонент повторно выполнить рендеринг с перехватами в React? или попробовать использовать этот пакет https://github.com/CharlesStover/use-force-update

Удачи:)

...