memo lets you skip re-rendering a component when its props are unchanged.
Wrap a component in memo to get a memoized version of that component. This memoized version of your component will usually not be re-rendered when its parent component is re-rendered as long as its props have not changed. But React may still re-render it: memoization is a performance optimization, not a guarantee.
memo作用
当数据变化时,代码会重新执行一遍,但是子组件数据没有变化也会执行,这个时候可以使用memo将子组件封装起来,让子组件的数据只在发生改变时才会执行
When a parent schedules an update by calling setState, by default React reconciles its whole child subtree. This is because React can’t know whether an update in the parent would affect the child or not, and by default, React opts to be consistent. This may sound very expensive but in practice, it’s not a problem for small and medium-sized subtrees.
When trees get too deep or wide, you can tell React to memoize a subtree and reuse previous render results during shallow equal prop changes:

Now setState in a parent <Table> component would skip over reconciling Rows whose item is referentially equal to the item rendered last time.
React.memo() and hooks
Components using hooks can be freely wrapped in React.memo() to achieve memoization.
React always re-renders the component if the state changes, even if the component is wrapped in React.memo().
1.Updating a memoized component using state
Even when a component is memoized, it will still re-render when its own state changes. Memoization only has to do with props that are passed to the component from its parent.
2.Updating a memoized component using a context
Even when a component is memoized, it will still re-render when a context that it’s using changes. Memoization only has to do with props that are passed to the component from its parent.
A React component should always have pure rendering logic. This means that it must return the same output if its props, state, and context haven’t changed. By using memo, you are telling React that your component complies with this requirement, so React doesn’t need to re-render as long as its props haven’t changed. Even with memo, your component will re-render if its own state changes or if a context that it’s using changes.
React intentionally doesn’t memoize components by default. Many components always receive different props so memoizing them would be a net loss.
Optimizing with memo is only valuable when your component re-renders often with the same exact props, and its re-rendering logic is expensive. If there is no perceptible lag when your component re-renders, memo is unnecessary. Keep in mind that memo is completely useless if the props passed to your component are always different, such as if you pass an object or a plain function defined during rendering. This is why you will often need useMemo and useCallback together with memo.
function A({children}){
console.log("A");
const[state, setState]=useState(0);
useEffect(()=>{
setState((state)=>state+1);
},[]);
return children;
}
/* Here even on state change of `A` parent component, child components will not re-render. When the parent state changes, parent component re-renders. But it still has the same children prop it got last time, so React doesn’t visit that subtree. And as a result, child component doesn’t re-render.
Thus there are two ways to prevent child components from re-rendering.
- wrapping them in `memo`
- passing them as `children` prop
*/
https://dmitripavlutin.com/use-react-memo-wisely/
shouldComponentUpdate
React.memo function was introduced, which allows functional components to have similar performance optimizations as class components with PureComponent.
import React, { memo } from 'react';
const MyFunctionalComponent = memo(function MyComponent(props) {
// ...
});
memo返回一个高阶组件,与PureComponent类似,如果输入props相同则跳过组件渲染,从而提升组件性能。
PureComponent属于Class Component实现,memo则用于创建function component
它会记忆上次输入prop的执行输出并提升应用性能。props比较是浅层的。
function MyComponent(props) {
/* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
/*
如果把nextProps传入render方法的返回结果与将prevProps传入render方法的返回结果一致则返回true,否则返回false
*/
}
export default React.memo(MyComponent, areEqual);
默认情况下其只会对复杂对象做浅层对比,如果想要控制对比过程,那么将自定义的比较函数通过第二个参数传入来实现。与shouldComponentUpdate()的返回值相反。
用户可以用自定义逻辑深度对比(deep comparison)对象。如果比较函数返回 false 则重新渲染组件,否则就不会重新渲染。
function CustomisedComponent(props) {
return (
<div>
<b>User name: {props.name}</b>
<b>User age: {props.age}</b>
<b>User designation: {props.designation}</b>
</div>
)
}
// The component below is the optimised version for the Default Componenent
// The Component will not re-render if same props value for "name" property
var memoComponent = React.memo(CustomisedComponent);
上面的组件将对前后两个 props 的值进行浅层比较。
如果将对象引用作为 props 传递给 memo 组件,则需要一些自定义比较。在这种情况下将比较函数作为第二个参数传递给 React.memo 函数。
假设 props 值(user)是一个对象引用,包含特定用户的name、age和designation。这种情况下需要进行深入比较。可以创建一个自定义函数,查找前后两个 props 值的 name、age 和 designation 的值,如果它们不相同则返回 false。
这样,即使将参考数据作为 memo 组件的输入,组件也不会重新渲染。
// The following function takes "user" Object as input parameter in props
function CustomisedComponent(props) {
return (
<div>
<b>User name: {props.user.name}</b>
<b>User age: {props.user.age}</b>
<b>User designation: {props.user.designation}</b>
</div>
)
}
function userComparator(prevProps, nextProps) {
if(prevProps.user.name == nextProps.user.name ||
prevProps.user.age == nextProps.user.age ||
prevProps.user.designation == nextProps.user.designation) {
return false
} else {
return true;
}
}
var memoComponent = React.memo(CustomisedComponent, userComparator);
Pitfall
If you provide a customarePropsEqual implementation, you must compare every prop, including functions. Functions often close over the props and state of parent components. If you return true when oldProps.onClick !== newProps.onClick, your component will keep “seeing” the props and state from a previous render inside its onClick handler, leading to very confusing bugs.
Avoid doing deep equality checks inside arePropsEqual unless you are 100% sure that the data structure you’re working with has a known limited depth. Deep equality checks can become incredibly slow and can freeze your app for many seconds if someone changes the data structure later.
React.memo 和 JS 的 memorize 函数的区别