Это хорошая практика для Stringify Object для useState () Хук, чтобы избежать повторного рендеринга - PullRequest
4 голосов
/ 22 марта 2020

Согласно , этим и , что вопрос, оператор распространения , кажется, используется для обновления объекта, управляемого в useState ловушке.

Я создал супер простой пример и обнаружил, что даже когда содержимое объекта не изменяется, запускается повторный рендеринг (это понятно, потому что объект изменился):

import React from "react";

function useFriendStatus() {
  const [person, setPersonProps] = React.useState({name:'Mark',age:23});

  React.useEffect(() => {
    console.log("rerender");
    const interval = setInterval(() => {
      setPersonProps({...person});   //simply set the object again -> no content changed
      console.log('update');
    }, 1000);
    return () => clearInterval(interval);
  }, [person]);


  return person;
}

export default function App() {
  const person = useFriendStatus();

  return <div className="App">Hello World: {"" + person.name}</div>;
}

Здесь вы видите скриншот из моего профилировщика, который показывает, что повторный рендеринг, похоже, запущен (даже если отображаемое имя не изменилось):

enter image description here

Мне интересно, является ли это «хорошей практикой», поскольку ВСЕ, кажется, перерисовывается. Иногда вы получаете глубоко вложенные объекты из API, и разбить их на супер-простые необъектные userState хуки невозможно.

Разве не лучше было бы все строчить?

import React from "react";


function useFriendStatus() {
  const [person, setPersonProps] = React.useState(JSON.stringify({name:'Mark',age:23}));

  React.useEffect(() => {
    console.log("rerender");
    const interval = setInterval(() => {
      const personCopy=JSON.parse(person);
      setPersonProps(JSON.stringify({...personCopy}));
      console.log('update');
    }, 1000);
    return () => clearInterval(interval);
  }, [person]);


  return person;
}

export default function App() {
  const person = JSON.parse(useFriendStatus());

  return <div className="App">Hello World: {"" + person.name}</div>;
}

Как вы справляетесь с этим на практике?

1 Ответ

1 голос
/ 22 марта 2020

Я создал супер простой пример и обнаружил, что даже когда содержимое объекта не изменяется, запускается повторный рендеринг (это понятно, потому что объект изменился)

Это не имеет ничего общего с «содержимым» объекта, ваши компоненты повторно визуализируют, потому что вы создаете поверхностную копию {...person} объекта (изменяя его ссылку).

На фазе рендеринга React поверхностное сравнение с предыдущим состоянием, чтобы решить, произойдет ли рендеринг, и в javascript, {} === {} всегда ложно.

оператор распространения, похоже, использоваться для обновления объекта, управляемого в хуке useState.

Поскольку состояние следует рассматривать как неизменяемый , обычно используется оператор распространения для создания мелкой копии.

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

Обычно просто добавляют условие перед вызовом setState:

React.useEffect(() => {
  const newPerson = { ...person }; // fetch from some source
  // or check if person.name !== newPerson.name
  if (!isEqual(person, newPerson)) {
    setPerson(newPerson);
  }
}, [person]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...