Как предотвратить повторный рендеринг компонента? (с помощью MWE)

#javascript #reactjs #canvas #react-hooks #components

#javascript #reactjs #холст #реагирующие крючки #Компоненты

Вопрос:

Как я могу предотвратить повторный рендеринг компонента, если его реквизиты не изменены?

Ссылка на изолированную среду кода / минимальный рабочий пример. Наведите курсор Canvas и увидите, что консоль регистрируется со многими "Canvas re-rendered" сообщениями.

На верхнем уровне я передаю const функцию в качестве обработчика в Canvas . Состояние onMouseMoveHandler обновлений App , чтобы он мог обновить Details компонент:

 <div className="App">
  <Canvas onMouseMoveHandler={onMouseMoveHandler} />
  <Details passedProp={getValue} />
</div>
 

Мне это нужно, чтобы оно Canvas не отображалось повторно, потому что HTML canvas -элемент внутри имеет нарисованные пользователем линии. Как я могу это сделать?

Я бы подумал, что использование React.memo сделает его похожим на чистый компонент, чтобы он не подвергался повторному рендерингу.

Я очень новичок в React, и если я не думаю о правильной структуре кода, дайте мне знать, как это исправить.

Ответ №1:

В вашем App.js каждый раз, когда вы вызываете setValue , ваш App компонент перезаписывает и создает новую onMouseMoveHandler функцию. Ваш Canvas компонент использует React.memo , но поскольку при каждом повторном рендеринге onMouseMoveHandler получает новую ссылку, он также выполняет повторный рендеринг. Чтобы предотвратить это, вам нужно обернуть свой onMouseMoveHandler with useCallback . useCallback вернет сохраненную версию обратного вызова, которая изменяется только в том случае, если изменилась одна из зависимостей. .

Вот пример:

 const onMouseMoveHandler = useCallback(() => {
   setValue(Math.random());
}, []);
 

Ответ №2:

Если вы обернете onMouseMoveHandler в a useCallback , это должно решить проблему. Проблема в том, что при изменении состояния ваш компонент приложения повторно рендерится, и onMouseMoveHandler функция получает новую ссылку. И, поскольку у него есть новая ссылка, это также приведет Canvas к повторному рендерингу, потому что он рассматривает это как изменение реквизита. Используя useCallback хук, вы гарантируете, что ссылка на функцию остается неизменной между рендерингом.

Ответ №3:

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

Вы можете проверить изменения здесь: https://codesandbox.io/s/determined-water-72uq4?file=/src/App.js:362-380