进一步认识 Hooks :如何正确理解函数组件的生命周期?
info
React的本质:从Model到View的映射
React 本身正是为动态的状态变化而设计的,而可能引起状态变化的原因基本只有两个:
- 用户操作产生的事件,比如点击了某个按钮。
- 副作用产生的事件,比如发起某个请求正确返回了。
这两种事件本身并不会导致组件的重新渲染,但我们在这两种事件处理函数中,一定是因为改变了某个状态,这个状态可能是 State 或者 Context,从而导致了 UI 的重新渲染。
在函数组件中你要思考的方式永远是:当某个状态发生变化时,我要做什么,而不再是在 Class 组件中的某个生命周期方法中我要做什么。
重新思考组件的生命周期
构造函数
在类组件中做一些初始化的事情。那么在函数式组件中我们怎么初始化一些东西呢?
:函数组件基本上没有统一的初始化需要,因为 Hooks 自己会负责自己的初始化。比如 useState 这个 Hook,接收的参数就是定义的 State 初始值。而在过去的类组件中,你通常需要在构造函数中直接设置 this.state ,也就是设置某个值来完成初始化。
构造函数的本质,其实就是:在所以其它代码执行之前的一次性初始化工作。
而在函数式组件中,其实我们要实现的就是一次性的代码执行
虽然没有直接的机制可以做到这一点,但是利用 useRef 这个 Hook,我们可以实现一个 useSingleton 这样的一次性执行某段代码的自定义 Hook,???不能使用useEffect来实现吗?
代码如下:
import { useRef } from 'react';
// 创建一个自定义 Hook 用于执行一次性代码
function useSingleton(callback) {
// 用一个 called ref 标记 callback 是否执行过
const called = useRef(false);
// 如果已经执行过,则直接返回
if (called.current) return;
// 第一次调用时直接执行
callBack();
// 设置标记为已执行过
called.current = true;
}
三种常用的生命周期方法
在类组件中,componentDidMount,componentWillUnmount,和 componentDidUpdate 是在开发中最常用的
使用useEffect来代替
useEffect 接收的返回值是一个回调函数,这个回调函数不只是会在组件销毁时执行,而且是每次 Effect 重新执行之前都会执行,用于清理上一次 Effect 的执行结果。
warning
useEffect 接收的 callback 是在依赖发生变化以及第一次时执行,return 的函数是在下一次 callback 执行之前执行,或者销毁时执行。当依赖项为空时只会在最后组件销毁时执行。