Когда нужен React.memo?
Компонент обновляется (перерисовывается), когда меняется его состояние. Когда обновляется компонент, обновляются все его дочерние компоненты и рекурсивно дочерние компоненты дочерних компонентов.
Компонент может иметь глубокую вложенность дочерних компонентов:
const C = () => <div />; const B = () => <C /> const A = () => <B />; const App = () => { return <A />; }
В примере выше, при обновлении компонента App
произойдет обновление всех вложенных компонентов: A
, B
и C
.
Обновление всех дочерних компонентов может быть нежелательно - если у компонента не меняется состояние и пропсы, то и обновлять его не надо. Обновление компонента можно остановить с помощью React.memo
(мемо). Мемо создает элемент, который ссылается на мемоизируемый компонент и содержит функцию сравнения пропсов для этого компонента:
export function memo(type, compare) { const elementType = { $$typeof: REACT_MEMO_TYPE, type, compare: compare === undefined ? null : compare, }; return elementType; }
При обновлении компонентов, React распознает мемо и вызывает функцию compare
чтобы определить изменились ли пропсы, если нет — можно пропустить обновление:
const prevProps = currentChild.memoizedProps; // Default to shallow comparison let compare = Component.compare; compare = compare !== null ? compare : shallowEqual; if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); }
Возвращаясь к первому примеру, обернем компонент A
в мемо:
const C = () => <div />; const B = () => <C /> const A = React.memo(() => <B />); const App = () => { return <A />; }
Теперь, при обновлении App
, компонент A
и его вложенные компоненты обновляться не будут, так как их пропсы не изменяются.
Использование мемо даст результат, если:
- компонент перерисовывается (обновляется) часто с одними и теми же пропсами.
- обновление компонента дорогое, например, когда у компонента большая вложенность дочерних компонентов.
Credits: foto by Oskar Yildiz https://unsplash.com/photos/gy08FXeM2L4
Top comments (0)