useMemo和useCallback的使用
useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。
也就是说useMemo可以让函数在某个依赖项改变的时候才运行,这可以避免很多不必要的开销。举个例子:
不使用useMemo
function Example() {
const [count, setCount] = useState(1);
const [val, setValue] = useState('');
function getNum() {
return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
}
return <div>
<h4>总和:{getNum()}</h4>
<div>
<button onClick={() => setCount(count + 1)}>+1</button>
<input value={val} onChange={event => setValue(event.target.value)}/>
</div>
</div>;
}
上面这个组件,维护了两个state,可以看到getNum
的计算仅仅跟count
有关,但是现在无论是count
还是val
变化,都会导致getNum
重新计算,所以这里我们希望val
修改的时候,不需要再次计算,这种情况下我们可以使用useMemo
。
使用useMemo
function Example() {
const [count, setCount] = useState(1);
const [val, setValue] = useState('');
const getNum = useMemo(() => {
return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
}, [count])
return <div>
<h4>总和:{getNum()}</h4>
<div>
<button onClick={() => setCount(count + 1)}>+1</button>
<input value={val} onChange={event => setValue(event.target.value)}/>
</div>
</div>;
}
使用useMemo
后,并将count
作为依赖值传递进去,此时仅当count
变化时才会重新执行getNum
。
useCallback
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。
看起来似乎和useMemo差不多,我们来看看这两者有什么异同:
useMemo
和useCallback
接收的参数都是一样,都是在其依赖项发生变化后才执行,都是返回缓存的值,区别在于useMemo
返回的是函数运行的结果,useCallback
返回的是函数。
useCallback(fn, deps) 相当于 useMemo(() => fn, deps)
使用场景
正如上面所说的,当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。也就是说父组件传递一个函数给子组件的时候,由于父组件的更新会导致该函数重新生成从而传递给子组件的函数引用发生了变化,这就会导致子组件也会更新,而很多时候子组件的更新是没必要的,所以我们可以通过useCallback
来缓存该函数,然后传递给子组件。举个例子:
function Parent() {
const [count, setCount] = useState(1);
const [val, setValue] = useState('');
const getNum = useCallback(() => {
return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b)
}, [count])
return <div>
<Child getNum={getNum} />
<div>
<button onClick={() => setCount(count + 1)}>+1</button>
<input value={val} onChange={event => setValue(event.target.value)}/>
</div>
</div>;
}
const Child = React.memo(function ({ getNum }: any) {
return <h4>总和:{getNum()}</h4>
})
使用useCallback
之后,仅当count
发生变化时Child
组件才会重新渲染,而val
变化时,Child
组件是不会重新渲染的。
useMemo和useCallback的使用的更多相关文章
- useMemo、useCallback简单理解
1.useMemo.useCallback都是使参数(函数)不会因为其他不想关的参数变化而重新渲染. (1)useMemo const memoDom = useMemo(() => { ret ...
- React中useMemo与useCallback的区别
useMemo 把"创建"函数和依赖项数组作为参数传⼊入useMemo,它仅会在某个依赖项改变时才重新计算memoized 值.这种优化有助于避免在每次渲染时都进⾏行行⾼高开销的计 ...
- useMemo优化React Hooks程序性能(九)
useMemo主要用来解决使用React hooks产生的无用渲染的性能问题.使用function的形式来声明组件,失去了shouldCompnentUpdate(在组件更新之前)这个生命周期,也就是 ...
- React Hooks: useCallback理解
useCallback把匿名回调“存”起来 避免在component render时候声明匿名方法,因为这些匿名方法会被反复重新声明而无法被多次利用,然后容易造成component反复不必要的渲染. ...
- React Hooks 深入系列 —— 设计模式
本文是 React Hooks 深入系列的后续.此篇详细介绍了 Hooks 相对 class 的优势所在, 并介绍了相关 api 的设计思想, 同时对 Hooks 如何对齐 class 的生命周期钩子 ...
- 如何构建自己的 react hooks
我们组的前端妹子在组内分享时谈到了 react 的钩子,趁此机会我也对我所理解的内容进行下总结,方便更多的同学了解.在 React 的 v16.8.0 版本里添加了 hooks 的这种新的 API,我 ...
- React Hooks用法大全
前言 在 React 的世界中,有容器组件和 UI 组件之分,在 React Hooks 出现之前,UI 组件我们可以使用函数,无状态组件来展示 UI,而对于容器组件,函数组件就显得无能为力,我们依赖 ...
- React 新特性学习
1 context 2 contextType 3 lazy 4 suspense 5 memo 6 hooks 7 effect hooks =========== 1 Context 提供了一种方 ...
- React Hook挖坑
React Hook挖坑 如果已经使用过 Hook,相信你一定回不去了,这种用函数的方式去编写有状态组件简直太爽啦. 如果还没使用过 Hook,那你要赶紧升级你的 React(v16.8+),投入 H ...
- React Hook~部分实用钩子
useCompareEffect /** * useCompareEffect * useEffect只是普通的浅比较,这里做了深比较 * useEffect的依赖是否相同,相同不触发 */ impo ...
随机推荐
- webpack 0-1 配置 以及 (性能优化)
五大核心: 模式 production developmentmode: 'development', 入口entry: './src/js/index.js', loader的配置module: { ...
- 大厂SSP的Java学习路线
现在互联网环境这么差,Java还能学吗? 学Java还能找到工作吗? 大家好呀, 我是程序员回家养猪, 一个专升本, 三段实习经历拿下大厂SSP offer的程序员博主. 关于我的个人经历, 之前文章 ...
- 使用MySQL Shell 8.4.1-LTS 直接将数据复制到 MySQL实例
在之前的文章中,我谈到了如何使用 MySQL Shell 通过多线程过程来转储和加载数据,以及如何以不同格式导出表数据,然后可以将这些数据导入到新的 MySQL 实例中.这篇文章将讨论我们如何直接将数 ...
- 安卓抓包之SocksDroid
之前一直使用电脑端的Charles代理软件, 然后手机端WiFi代理设置为Charles的代理ip与端口, 也就是8888 但是发现有些软件的请求包是抓取不到的, 于是查看apk源码发现发送网络请求使 ...
- Golang之数据库转换结构体工具table2struct
另外一个根据json生成对应结构体在线工具: https://mholt.github.io/json-to-go/ 安装: go get github.com/gohouse/converter 或 ...
- Xdebug+Phpstorm远程调试
开发环境: 本地 Windows10 日常开发使用的环境 装有PHPStorm 远程主机 Linux 服务器 装php-fpm/nginx等所有开发依赖环境 本地可以访问远程主机 但远程主机无法访问本 ...
- uView的DatetimePicker组件在confirm回调中取不到v-model的最新值
前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验非常棒,公司项目就是主推uni-app,在uniapp生态中u ...
- 鸿蒙UI布局实战 —— 个人中心页面开发
1.前言 接下里我们将开启"鸿蒙UI布局系列"的学习,第一站:学习线性布局(Row/Column)+ 弹性布局(Flex) 在展开学习前,先上一个实战demo--开发一个个人中心页 ...
- openEuler欧拉部署Redis
一.系统优化 关闭防火墙 systemctl stop firewalld systemctl disable firewalld 关闭selinux sed -ri 's/SELINUX=enfor ...
- 【Amadeus原创】查找docker里程序源代码路径 上传本地文件
1. 先找到container id ,诸如,我要进wikijs. id为3f6d2092f6ba docker ps 2. docker exec 进入container里面 docker exec ...