Когда нужен 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)