-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
简单聊一聊 useEffect #25
Labels
react
react 笔记整理
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
翻到几篇文章, 发现之前对于
useEffect
这个 hook 的认识是有问题的, 这里稍微重新整理一下基本点
官网其实对
useEffect
的讲解已经很清晰了:对于这么一个函数:
有这么几个点:
useEffect
的回调函数的调用在render phase
之后, 并且是在渲染至屏幕之后, 这里与useLayoutEffect
不同, 不展开cleanup
函数不仅仅只是在组件unmount
的时候触发, 如果该组件存在多次 render 的情况, 也会触发, 同时触发时机在"下次"useEffect
的回调函数触发之前虽然 hooks 官方并没有给出生命周期图, 但是网上有人制作了一份还是很清晰的:
示例
以最基本的计数器为例, 如下:
过程简化如下:
mount
的时候, 先render
一次useEffect
里的回调render
一次count
状态, 执行useEffect
里的返回函数useEffect
里的回调因此控制台的输出结果依次如下
效果图如下:
每次都运行
当没有依赖数组的时候,
useEffect
里的回调函数在每次 render 的时候都会执行, 即初始 mount 的时候以及后续组件状态改变重新 re-render 的时候只有 mount 才运行
当依赖数组是空时,
useEffect
里的回调函数只在第一次 render 即 mount 之后执行mount 和特定 update 运行
当依赖数组里存在依赖项, 例如组件的 state 或者 props, 当其中任一一个依赖项发生变动时,
useEffect
执行其中的回调函数只有特定 update 运行
这个需求是我需要
console.log()
这条语句只在组件更新的时候触发, 组件第一次渲染 mount 的时候不触发, 实现也很简单, 通过ref
或者全局变量的状态控制当然这里
useEffect
依旧会在 mount 之后执行, 只是里面的判断使得有条件的执行更具体点的可以抽成一个自定义 hook, 如下:
组里里使用:
usePrevious
由于
useEffect
里的回调函数是在render
之后进行的, 可以根据这一个机制获取到之前的状态的值.使用:
打印结果为:
效果如下:
需要注意的是, 这里的实现不一定需要强制使用
ref
, 用一个全局变量也是一样的, 只是ref
提供了一样的功能, 即useRef
提供的引用在整个组件的声明周期都是持久并且是最新的.ref
一个比较好的作用就是能够解决 hooks 的陈旧闭包问题, 之前的博客里有写, 这里不多描述, 有兴趣可以看这个问题以及我之前的文章cleanup
如上述提到的, cleanup 函数不仅仅是在 unmount 才执行, 每次组件更新的时候也会执行, 用于消除上次存在的不用资源
以实现自增器为例, 其实可以有很多种写法, 第一种如下:
这里每次更新导致
useEffect
执行都会创建一个新的 interval, 而每次的 cleanup 函数都用于清除上次运行时创建的定时器. 这么做虽然没问题但是他的机制在于, 每次都会创建新的定时器, 而我们所需要的往往只是一个定时器实例, 并且每次定时器只跑了一秒就被清除更好的做法是稍微修改一下依赖数组:
保证在 mount 之后只存在一个定时器实例, 同时该定时器在组件 unmount 时也能被销毁.
当然上述需求用
setTimeout
实现也是可以的:参考
The text was updated successfully, but these errors were encountered: