React.memo是什么?
在写函数式组件的时候,为了避免无效的渲染,可以通过 React.memo
函数来实现,类似于 React.PureCompnent
的功能,对 props
进行浅比较,代码如下
function MyComponent(props) {
}
function areEqual(prevProps, nextProps) {
// 手动判断是否需要重新渲染
// return true不渲染,false则渲染
}
export default React.memo(MyComponent, areEqual);
React.memo
第二个参数不用的话默认就 props 浅比较
React.memo
在跟某些hooks配合使用的情况下会失效,例如在组件内部使用 useState
,useReducer
,useContext
,当 state 或者 context 改变时,组件还是会重新渲染
React.memo和useContext
在配合useContext使用的情况下,当 context 变化,函数组件会重新渲染,如何解决呢?
避免context的值太过于复杂,尽量拆分细粒度的context值
拆分组件多个context,比如AppContext,ThemeContext,AudioContext 等等,这样其他 context 改变就不会导致无关组件的渲染
function Button() {
let theme = useContext(ThemeContext);
return <ExpensiveTree className={theme} />;
}
拆分组件,与使用 context 组件分离,在 render 阶段单独通过 memo 来缓存组件
const Button = () => {
const {
theme
} = useContext(ThemeContext);
return <button>click { theme }</button>
}
export default momo(Button);
改写为
const ThemeButton = memo(({ theme }) => {
return <button>click { theme }</button>;
})
const Button = () => {
const {
theme
} = useContext(ThemeContext);
return <ThemeButton theme={theme} />;
}
export default Button;
配合 useMemo 来渲染组件
function Button() {
let { theme } = useContext(AppContext);
return useMemo(() => {
return <ExpensiveTree className={theme} />;
}, [theme])
}