#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