Разве useState не вызывает повторное рендеринг при работе с состояниями объекта? - PullRequest
1 голос
/ 20 апреля 2019

У меня есть firebase проект с firestore database document, который выглядит следующим образом.

document-id => 
    item1 => {detail: "value", title: "value", image: "value}
    item2 => {detail: "value", title: "value", image: "value}
    ...

Мой React component, который отображает это выглядит примерно так:

const [data, setData] = useState({});

useEffect(() => {
  firebase.getDocument("path-to-document").then(section => {
    if (section) {
      setPanels(section.data());
    }
  });
}, []);

const handleChange = (id, data) => {
  const payload = data;
  payload[id] = { ...panels[id], ...data };
  setData(payload);
}

return (<div>
  {Object.keys(data).map((key) => <Card
    data={data[key]}
    onChange={handleChange} />)}
</div>);

Я удалил дополнительный код из этого, но компонент Card просто устанавливает макет для отдельных объектов. При изменении он вызывает функцию handleChange правильно, а data State корректно обновляется до новых значений (вызов console.log(data) после того, как вызов метода setData показывает это). Однако component не reRender с новыми значениями для data.

Есть ли способ заставить компонент перерисоваться? В другом месте онлайн я обнаружил, что React «выдает» из повторного рендеринга, если setData вызывается с теми же данными, что и в данный момент, то есть никаких реальных изменений не будет.

Или, наоборот, есть другой способ обработать это взаимодействие и позволить компоненту Card обрабатывать постоянство данных?

спасибо.

1 Ответ

3 голосов
/ 20 апреля 2019

Попробуйте установить копию вашей полезной нагрузки : {...payload}:

const handleChange = (id, data) => {
  const payload = data;
  payload[id] = { ...panels[id], ...data };
  setData({...payload});
}

Поскольку вы не меняете состояние, ваше приложение не реагирует иrerenders.

Извлечение Функциональные обновления в Реакция документов .

const handleChange = (id, data) => {
  const payload = data;
  payload[id] = { ...panels[id], ...data };
  setData(prevPayload => {
      console.log(prevPayload === payload)            // true
      return payload                                  // No Re-Render

      // console.log(prevPayload === { ... payload }) // false
      // return { ... payload }                       // Re-render
  );
}

Изучите этот пример на codesandbox .

...