React中useCallback useMemo使用方法快速精通
作者:星海拾遗
首先从简单的讲一下两者的区别
useCallback和useMemo的区别
基本使用
// 贴上代码片利于复制 import { React, useState, useMemo, useCallback } from "react"; export default function TestPage() { const callBack = useCallback(() => { console.log(1); }, []); const memo = useMemo(() => 123, []); console.log("callback", callBack); console.log("memo是", memo); return ( <div> <div>一个专门用于vue测试的页面</div> </div> ); }
控制台输出如下
可以直观的看到,useCallBack返回的是一个函数,useMemo返回的是一个变量。
接下来我们来剖析这两个东西的用法
useMemo
首先从简单的讲起,如果你学过Vue的话,完全可以把它当成Computed来理解。在这里举一个很好理解的
import { React, useState, useMemo, useCallback } from "react"; export default function TestPage() { const [data, updateData] = useState(1); const getComplicatedValue = () => { console.log("开始计算一个复杂的value值啦!"); let total = 0; for (let i = 0; i < 100; i++) { total += i; } return total; }; const changeData = () => { updateData((oldValue) => oldValue + 1); }; return ( <div> <div>一个专门用于vue测试的页面</div> <div>这是一个复杂函数计算出来的值{getComplicatedValue()}</div> <div>这是一个简简单单的data值{data}</div> <button onClick={changeData}>点击我改变data值</button> </div> ); }
大意就是,页面上有一个很简单的值data,还有一个很复杂的经过函数计算出来的值getComplicatedValue,这里我用从1加到100来模拟了一个很复杂的计算过程(实际项目会更复杂)。
页面显示如下
显示正常,根据控制台显示也可以看到getComplicatedValue函数也被正常调用了。接下来我们点击按钮改变data的值。
可以看到页面是正常更新了的,但是性能问题出现了,我改变了data的值,导致render函数重新执行,然后getComplicatedValue又被执行了一遍!也就是计算机重新计算了1加到100。那么问题出现了,如果我是1加到100000呢?很显然,在我们更新data值的时候,并不需要getComplicatedValue再次执行,而是希望它的计算值被缓存起来。useMemo闪亮登场!!!当当当当。
改写如下,改写只需要改动两行
import { React, useState, useMemo, useCallback } from "react"; export default function TestPage() { const [data, updateData] = useState(1); const getComplicatedValue = useMemo(() => { console.log("开始计算一个复杂的value值啦!"); let total = 0; for (let i = 0; i < 100; i++) { total += i; } return total; },[]); const changeData = () => { updateData((oldValue) => oldValue + 1); }; return ( <div> <div>一个专门用于vue测试的页面</div> <div>这是一个复杂函数计算出来的值{getComplicatedValue}</div> <div>这是一个简简单单的data值{data}</div> <button onClick={changeData}>点击我改变data值</button> </div> ); }
第四行把getComplicatedValue函数用useMemo包裹起来。第18行删除(),因为刚刚已经说过,useMemo返回的是一个值而不是函数。
接下来再看看页面效果
这次可以看到,无论data值更新多少次,getComplicatedValue永远只执行了初始化的那一次。
来个首尾呼应
基本使用
const memo = useMemo(() => {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->},[依赖项数组])
如果依赖项数组里面的数据没有变化,那么memo值永远使用缓存,而不会重新计算
useCallback
useCallback比起useMemo就难上了一丢丢,因为涉及到了子组件。当然也是灰常简单。
首先来看一个简单
父组件
import { React, useState, useMemo, useCallback } from "react"; import TestSonComp from "./testSonComp"; export default function TestPage() { const [data, updateData] = useState(1); const getValue = () => { console.log("我是父组件的一个函数"); }; const changeData = () => { updateData((oldValue) => oldValue + 1); }; return ( <div> <div>一个专门用于vue测试的页面</div> <div>这是一个简简单单的data值{data}</div> <button onClick={changeData}>点击我改变data值</button> <TestSonComp getValue={getValue} /> </div> ); }
子组件
import { React, memo } from "react"; const TestSonComp = (props) => { console.log("子组件render函数执行了"); return <div>一个子组件</div>; }; export default TestSonComp;
页面显示正常,然后点击按钮更新数据
那么此时问题又出现了,我就是在父组件中改了一下data值,data值导致父组件render重新执行,render生成了一个新的getValue函数,然后子组件props更新,导致子组件更新。那么有没有一个方法可以把函数缓存起来呢?
useCallback闪亮登场。
直接改写父组件定义函数的一行
const getValue = useCallback(() => { console.log("我是父组件的一个函数"); }, []);
改完之后看页面效果你依然会发现和上图一样,子组件依然会更新!
问题出在这
useCallback必须配合React.memo来使用
react的Hooks组件对props的浅比较是在memo里面比较的(类组件是在shouldComponentUpdate里面),如果没有memo,那么你使用useCallback就没有意义
怎么使用?
子组件直接改写最后一行
export default memo(TestSonComp);
二话不说看效果
改写成功
再来个温故知新
基本使用
const callback = useCallback(() => {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->},[依赖项数组])
如果依赖项数组里面的数据没有变化,那么函数值也永远使用缓存。
到此这篇关于React中useCallback useMemo使用方法快速精通的文章就介绍到这了,更多相关React useCallback useMemo内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!