Причины перерисовки компонентов в React
В React перерисовка (re-render) — это процесс, при котором компонент заново вызывается, чтобы React мог построить новое виртуальное дерево и сравнить его с предыдущим.
Разработчику важно понимать, что именно может вызвать перерисовку, чтобы оптимизировать производительность и избежать лишних обновлений.
Основные причины перерисовки
Изменение state
При вызове setState
(например, setCount
) компонент всегда перерисовывается.
const [count, setCount] = useState(0);
setCount(count + 1); // вызывает перерисовку
Изменение props
Если компонент получает новые значения пропсов, он тоже будет перерендерен.
<Child value={someValue} /> // если someValue изменился → ререндер
Родительский компонент перерендерился
Если родитель обновился, все его дочерние компоненты тоже вызываются снова,
если они не оптимизированы (React.memo
, shouldComponentUpdate
).
Изменение контекста (Context)
Если вы используете useContext
, и значение контекста меняется —
все компоненты, которые его используют, перерисуются.
Принудительный ререндер (force update)
Например, через useReducer
, useSyncExternalStore
или сторонние хранилища —
можно вручную инициировать обновление компонента.
Как избежать лишних ререндеров
Метод | Что делает |
---|---|
React.memo(Component) | Кэширует компонент, не обновляет без изменений props |
useMemo(fn, deps) | Кэширует вычисления между рендерами |
useCallback(fn, deps) | Кэширует функции, передаваемые вниз по дереву |
useRef() | Хранит данные без ререндера компонента |
key | Контролирует идентичность компонентов в списках |
Пример лишнего рендера
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<Child />
<button onClick={() => setCount(count + 1)}>+1</button>
</>
);
}
function Child() {
console.log("Child ререндерится");
return <div>Я ничего не меняю</div>;
}
Даже если Child
не использует count
, он всё равно ререндерится, потому что родитель обновился.
Решение
const Child = React.memo(() => {
console.log("Child ререндерится");
return <div>Я ничего не меняю</div>;
});
Ловушка: новое значение по ссылке
const obj = { a: 1 };
<Component data={obj} />
Каждый раз создаётся новая ссылка, даже если данные те же → перерисовка. Используйте useMemo
или useCallback
, чтобы сохранить ссылку.
Итог
- Компоненты в React ререндерятся при изменении
state
,props
,context
или родителя - Оптимизация возможна с помощью
React.memo
,useMemo
,useCallback
иuseRef
- Избегайте передачи новых объектов и функций без необходимости
Совет:
Оптимизируйте только те компоненты, которые реально создают нагрузку. Преждевременная оптимизация — зло.