【react-hook】 useCallback
hook
- useEffect
- useCallback
开始之前请注意这句话:任何优化都会增加复杂性,任何过早添加的优化都会带来风险,因为优化后的代码可能会多次更改
useEffect
相关作用:监听 & 初始化
//最简单用法useEffect(() => {//只有方法体,相当于componentDidMount和componentDidUpdate中的代码document.title = count;})//加返回值用法useEffect(() => {//添加监听事件,相当于componentDidMount和componentDidUpdate中的代码window.addEventListener('resize', onChange, false);//返回的函数用于解绑事件,相当于componentWillUnmount中的代码return () => {window.removeEventListener('resize', onChange, false)}})//加空数组参数用法useEffect(() => {// 相当于 componentDidMountwindow.addEventListener('resize', onChange, false)return () => {// 相当于 componentWillUnmountwindow.removeEventListener('resize', onChange, false)}}, []);//加监听值用法useEffect(() => {//只有当count的值发生变化,此函数才会执行console.log(`count change: count is ${count}`)}, [ count ]);
useCallback
先看一个最简单的例子:
// 用于记录 getData 调用次数
let count = 0;
function App() {const [val, setVal] = useState("");function getData() {setTimeout(()=>{setVal('new data '+count);count++;}, 500)}useEffect(()=>{getData();}, []);return (<div>{val}</div>);}
getData模拟发起网络请求。在这种场景下,没有useCallback什么事,组件本身是高内聚的。
如果涉及到组件通讯,情况就不一样了:
// 用于记录 getData 调用次数let count = 0;
function App() {const [val, setVal] = useState("");function getData() {setTimeout(() => {setVal("new data " + count);count++;}, 500);}return <Child val={val} getData={getData} />;}function Child({val, getData}) {useEffect(() => {getData();}, [getData]);return <div>{val}</div>;}
就这么轻轻松松,一个死循环就诞生了…
先来分析下这段代码的用意,Child组件是一个纯展示型组件,其业务逻辑都是通过外部传进来的,这种场景在实际开发中很常见。
再分析下代码的执行过程:
- App渲染Child,将val和getData传进去
- Child使用useEffect获取数据。因为对getData有依赖,于是将其加入依赖列表
- getData执行时,调用setVal,导致App重新渲染
- App重新渲染时生成新的getData方法,传给Child
- Child发现getData的引用变了,又会执行getData
- 3 -> 5 是一个死循环
如果明确getData只会执行一次,最简单的方式当然是将其从依赖列表中删除。但如果装了 hook 的lint 插件,会提示:React Hook useEffect has a missing dependency
useEffect(() => {getData();}, []);
实际情况很可能是当getData改变的时候,是需要重新获取数据的。这时就需要通过useCallback来将引用固定住:
const getData = useCallback(() => {setTimeout(() => {setVal("new data " + count);count++;}, 500);}, []);
上面例子中getData的引用永远不会变,因为他它的依赖列表是空。可以根据实际情况将依赖加进去,就能确保依赖不变的情况下,函数的引用保持不变。
还有一个要注意的是
在开始监听一个鼠标的移动的时候,想要删除这个监听不生效,由于是, 加入useState导致组件再次渲染 handleMouse 函数在次渲染, handleMouse 作为组件内的方法, 会跟着一同再次渲染, 并且在内存里, 再次渲染出的 clickFunc !== 前clickFunc.
所以removeEventListener无法解除绑定, 再次addEventListener则会绑定一个新方法.
document.addEventListener('mousemove',handleMouse,true)
解决方案 : useCallback 缓存改方法 这时候的 document.removeEventListener(‘mousemove’,handleMouse,true) 中的handleMouse 和添加中的方法就是一个了,就能删除了。
onst handleMouse= useCallback(() => {//xxxxconsole.log("clicking");}, []);
【react-hook】 useCallback相关推荐
- 【React深入】深入分析虚拟DOM的渲染原理和特性
导读 React的虚拟DOM和Diff算法是React的非常重要的核心特性,这部分源码也非常复杂,理解这部分知识的原理对更深入的掌握React是非常必要的. 本来想将虚拟DOM和Diff算法放到一篇文 ...
- 【React组件】写一个模仿蓝湖的图片查看器
前言 最近公司让写一个可以自由拖拽放大的图片查看器,我寻思这还不简单,一顿操作猛如虎,俩小时后: 事实证明,一旦涉及到 DOM 的变换操作,如果很多细节考虑不全,抓过来就写,那基本就凉了.于是我仔细分 ...
- 【React 基础】之 React 面向组件编程
准备工作 使用 React 开发者工具调试 复习 类 相关知识 定义 class(类),代码如下: // 创建一个 Person 类 class Person {// 构造器方法constructor ...
- 【React 基础】之 React 基本介绍、jsx 规则、模块与组件
React 全家桶 React 基础 React-Router 路由 PubSub + 消息管理库 Redux 集中式的状态管理 Ant-Design UI 组件库 - React 简介 官网 英文官 ...
- 【React学习】React更新渲染原理
当我们调用 setState 之后发生了什么?react经历了怎样的过程将新的 state 渲染到页面上? 一次react更新,核心就是对虚拟dom进行diff,找出最少的需要变化的dom节点,然后对 ...
- 【React Native】iOS原生导航跳转RN页面
上一篇介绍了React Native使用react-navigation进行导航跳转页面,现在我们介绍下原生iOS中怎么导航进一个新的React Native页面. 一.原生跳转React Nativ ...
- 【React Native】react-navigation导航使用方法
目录 集成react-navigation 使用react-navigation 上一篇介绍了如何在已有iOS项目中集成React Native.这一篇我们把上一篇的demo做下拓展,添加点击电影跳转 ...
- 【React系列】状态(State)和生命周期
在上一篇中写过,组件可以分为函数式组件和类组件,并且更新组件的方法也给出了通过传入ReactDOM.render()方法进行更新.但是这种方式并不能很好地进行封装成独立功能的组件,一些操作会由外部进行 ...
- 【react开发】使用swiper插件,loop:true时产生的问题解决方案
这2天上班遇到的问题:react使用swiper3插件实现banner轮播,其中有个banner图有个click点击事件,而其他的是页面跳转.出现了一个问题: 就是向右滑动到该帧时的swiper,点击 ...
- reactnative 获取定位_【React Native】定位获取经纬度,当前城市等地址信息
最近做React Native时,需要用到城市定位的功能,React Native中文网的定位部分中也提供了相应的方法.主要用到的方法有: 这里只需要获取到经纬度,城市等信息,持续监听的函数就不需要了 ...
最新文章
- “我太喜欢你了”——友情的表达方式?
- eclipse占用内存过大_Java性能调优学习(三)-jmap+mat分析内存溢出问题实战
- Numpy出现TypeError: integer argument expected, got float的分析与解决
- 奥南朵 | 21天提升幸福感正念冥想
- python函数递归 字符串反转
- 微型计算机机安装硬盘教程,台式机械硬盘怎么安装?机械硬盘安装图解教程(SATA固态可参考)...
- 电商销售数据分析(Python)
- 实验六 教务管理数据库的设计
- 捡到的苹果手机怎么解id锁_苹果手机软解和硬解的区别
- LAB3 PartA 用户环境与异常处理
- 以推理游戏开始2007年吧!
- win10安装Mingw,看这里!
- html5鼠标移过切换图片,鼠标移动到图片上切换到另一张图片,移出时又切默认图片...
- 架构系列---利用zookeeper 分布式锁解决缓存重建冲突实战
- 「儒系」产品经理:管理预期,做好增长的3个核心要素
- 专访宜信AI中台团队负责人王东:智慧金融时代,大数据和AI如何为业务赋能
- 淘宝排名查询接口,关键词排名api,淘宝商品排名查询api,淘宝关键词搜索查询接口
- JavaScript代码题--以及一些奇奇怪怪的发现
- 如何使用Django和Celery为Web构建进度栏
- 《Activiti/Flowable 深入BPM工作流》-如何设置local流程变量?