React 中的 useCallback 钩子函数
1、useCallback 钩子函数简要说明
useCallback 钩子函数有点像 useMemo 一样可以备份信息,而 useCallback 只是备份函数,除非某些参数发生变化,否则他不会重新运行其中的代码,
2、useCallBack 例子
// 父级组件
const UseCallBackDemo: React.FC = () => {
const [num, setNum] = useState<number>(0);
const [dark, setDark] = useState<boolean>(false);
const getList = () => {
return [num, num + 1, num + 2];
};
const themeStyles = {
backgroundColor: dark ? "black" : "white",
color: dark ? "white" : "black",
};
return (
<div style={themeStyles}>
<input
value={num}
onChange={(e) => {
setNum(+e.target.value);
}}
></input>
<button
onClick={() => {
setDark((prve) => (prve = !prve));
}}
>
改变主题
</button>
<UseCallBackList lists={getList} />
</div>
);
};
// UseCallBackList 组件
type params = {
lists: Function;
};
const UseCallBackList: React.FC<params> = ({ lists }) => {
const [list, setList] = useState<any>([]);
useEffect(() => {
console.log("params change");
setList(lists());
}, [lists]);
return list.map((item: number, index: number) => <p key={index}>{item}</p>);
};
出现的问题:运行上述代码后,当我们在输入框中输入数字后,再去查看控制台的日志我们可以看到打印出了params change
的信息,这就表示UseCallBackList
组件的useEffect
钩子监听到了数据的改变,但是当我们点击改变主题按钮的时候,控制台也打印出了params change
的信息。
这是因为每次渲染应用程序组件时都会重新创建应用程序组件内部的 getList
函数,因此每次修改输入框中的值后都会重新创建该函数,所以当此函数传递给UseCallBackList
组件时都会是新函数,这样每次点击以后都会重新触发。
使用 useCallBack 钩子解决
const getList = useCallback(() => {
return [num, num + 1, num + 2];
}, [num]);
这样修改后,上述的问题就会解决。但是我们发现useCallBack
函数语法和useMemo
函数一样,但是他们还是存在不同,useCallBack
备份的是函数,而useMemo
是备份函数处理后的结果,所以 useMemo 是不能传递参数的。
就比如上述例子中我们可以在useCallBack
中传入增量,而在子组件调用 getList 函数时,就可以传入变量值,具体的例子如下:
// 父级组件
const getList = useCallback(
(increment: number) => {
return [num + increment, num + 1 + increment, num + 2 + increment];
},
[num]
);
// UseCallBackList 组件
useEffect(() => {
console.log("params change");
setList(lists(2));
}, [lists]);