React小技巧-React.memo useMemo useCallback
原文: https://piyushsinha.tech/series/optimizing-react?ck_subscriber_id=1555690090
本文例子github Demo:https://github.com/CHJ30/react-tips
1. React.memo(comp,[areEqual(prevProp,nextProps)])
- 场景:父组件中有N个小组件,其中有父组件给子组件传值后子组件频繁更新渲染,也有子组件不频繁渲染的组件。
- 第二个参数为空时,默认比较传递给子组件的参数为原始值时(number,string,boolean,null,undefined),并且参数与上次传递的传输相等时,React.memo才会避免重复渲染(因为React.memo是用referential equality 引用相等作为判断)
- 第二个参数不为空时,使用第二个参数(相等判断参数)作为是否需要重新渲染的判断一句
- 小Demo
- 父组件:
import React, { useState } from "react";
import Child1 from "./Child1";
import Child2 from "./Child2";
export default function ReactMemo() {
const [count, setCount] = useState(0);
return (
<div>
<button
onClick={() => {
setCount((count) => count + 1);
}}
>
count
</button>
<Child1 count={count} />
<Child2 string={"我是一段字符串"} />
</div>
);
}
- 子组件1(频繁更新
import React from "react";
export default function Child1(props) {
return (
<div>
<span>我是一直变化的组件</span>
<span>{props.count}</span>
</div>
);
}
- 子组件2(不频繁更新
import React from "react";
export default function Child2(props) {
return (
<div>
<span>我是不会变化的组件</span>
<span>{props.string}</span>
</div>
);
};
点击按钮后使用React devtool来抓取渲染时间
可以看到子组件2花费了部分时间渲染
使用React.memo
import React from "react";
export default React.memo(function Child2(props) {
return (
<div>
<span>我是不会变化的组件</span>
<span>{props.string}</span>
</div>
);
});
重新点击,发现子组件2的没有被重复渲染
2. useMemo
- 由于React.memo的判断限制,那有什么可以帮助我们当参数为非原始值时做一个参数缓存呢。答案是useMemo。
- 小Demo
将父组件修改为
import React, { useState, useMemo } from "react";
import Child1 from "./Child1";
import Child2 from "./Child2";
export default function UseMemo() {
const [count, setCount] = useState(0);
const person = { name: "chj" };
const memoizedPerson = useMemo(() => person, []); // 这里使用
return (
<div>
<button
onClick={() => {
setCount((count) => count + 1);
}}
>
count
</button>
<Child1 count={count} />
<Child2 person={memoizedPerson} />
</div>
);
}
效果确实是减少了重复渲染
2. useCallback
- 同理,当传递函数时,使用useCallback包裹即可
useCallback(fn, deps)
相当于useMemo(() => fn, deps)
const handleClick = () => {};
const memoizedHandleClick = useCallback(handleClick, []);