API memo в React
Прежде чем мы рассмотрим следующий хук,
необходимо упомянуть и о полезном API
memo
, который помогает нам
избегать повторного рендеринга компонента,
если его пропсы остаются неизменными.
Давайте разберем это на примере. Создадим
комопонент App
, в котором будет два
инпута, в которые, предположим, вводятся
имя и фамилия:
return (
<div>
<label>
name:
<input value={name} onChange={(e) => setName(e.target.value)} />
</label>
<br />
<label>
surname:
<input value={surn} onChange={(e) => setSurn(e.target.value)} />
</label>
</div>
);
Добавим в начало компонента стейты для них:
const [name, setName] = useState('');
const [surn, setSurn] = useState('');
Сделаем еще и дочерний компонент
Child.js
, пусть он выводит
приветствие, в котором будет отображаться
вводимое имя. Также в консоли будет выводится
строка 'child render'
при
каждом рендеринге этого компонента:
function Child({ name }) {
console.log('child render');
return <h3>Hello {name}!</h3>;
}
Добавим Child
в верстку основного
компонента после последнего инпута
и будем в качестве пропса передавать
ему имя:
<Child name={name} />
Импортируем его в основной комопонент:
import Child from './Child';
А теперь откроем консоль и будем в поля ввода вбивать имя и фамилию. Здесь мы увидим, что даже при вводе символов в поле для фамилии, наш дочерний компонент будет каждый раз перерисовываться. Никаких проблем, ведь у нас небольшой компонент. Но представьте, если бы этот компонент отображал большое количество данных и при этом, каждый раз перерисовывался.
А сейчас давайте обернем дочерний
компонент в memo
, и посмотрим,
как изменится рендеринг. Для начала
импортируем в него memo
:
import { memo } from 'react';
Затем создадим новую переменную и
присвоим ей наш Child
, обернутый
в memo
. У нас получится следующее
функциональное выражение:
const Child = memo( function Child({ name }) {
console.log('child render');
return <h3>Hello {name}!</h3>;
});
Откроем консоль и будем снова вводить имя и фамилию в поля. Сейчас мы видим, что при введении фамилии, наш дочерний компонент не перерисовывается.
Нужно помнить, что это не будет работать, если при неизменных пропсах будут меняться стейты, задействованные комопонентом или контекст, использующий изменения.
Возьмите код компонента App
,
который мы делали на этом уроке, оставьте
в нем только первый инпут. Создайте React
компонент Text
, содержащий абзац
с текстом 'long text'
, и
разместите его в App
после инпута.
В компоненте Text
добавьте
строчку console.log('text render');
.
Убедитесь, что при вводе символов
в инпут компонент Text
перерисовывается каждый раз.
А теперь оберните компонент
Text
в memo
. Убедитесь,
что при вводе символов в инпут
компонент Text
не перерисовывается
повторно.