前言
我还依稀记得在我还比较小的时候,一位乡村医生(我爷爷)曾这样告诉我这样一句话:"是药皆有三分毒",所以自从听到了这句话过后,每次生病拿药过后,感觉自己快要好了,就不会再谨遵医嘱把药全部吃完了。这里所说"三分毒"就是用药后的副作用。
我们都知道在 React 中,首次记载或属性状态值发生变化时,组件树都会渲染或重渲染,前面我们已经学习过状态,属性的管理,以及组件渲染过程,那如果我们要在组件渲染完成后,获取 DOM 或者 做一些其他的操作的时候该怎么来处理呢?本节我们就又多学习一个 React 钩子——useEffect。
useEffect 钩子
单词 effect:效应,影响,效果的意思,我们再对效应,影响,效果进行分析,这几个词是不是都是表达,在某一件事情之后,即一件事情的后续,预知后续如何,请听下回分解…哈哈哈,我们继续。
我们先来看这样一个例子,新建一个今日待办的组件,我们来尝试一下,打印出勾选的状态:
import { useState } from "react";
function TodoItem () {
const [checked, setChecked] = useState(false);
alert(`checked:${checked}`);
return(
<div className="check-item">
<label htmlFor="input">今日待办:</label>
<input
type="checkbox"
checked={checked}
value={checked}
style={{marginLeft: '6px'}}
onChange={(e) => { setChecked(checked => !checked); }}
/>
</div>
)
}
export default TodoItem;
我们知道,alert 方法会阻塞代码执行,也就是在 alert 弹出提示的时候,组件还没有进行渲染,相当于就是我们在渲染组件之前就已经去获取了选择状态,试想一下,我们怎么才能在组件渲染之后进行状态的打印呢?放在 return 方法之后行不行,我们知道函数中 return 会直接跳出函数,之后的代码就不会再执行了。所以,怎么在我完成了今日待办后给出提示?React 给我们提供的 useEffect 钩子这个时候就派上用场了。
我们来看一下,添加了 useEffect 钩子是什么样的呢?
import { useState, useEffect } from "react";
function TodoItem () {
const [checked, setChecked] = useState(false);
useEffect(() => {
console.log(`checked:${checked}`);
});
return(
<div className="check-item">
<label htmlFor="input">今日待办:</label>
<input
type="checkbox"
checked={checked}
value={checked}
style={{marginLeft: '6px'}}
onChange={(e) => { setChecked(checked => !checked); }}
/>
</div>
)
}
export default TodoItem;
从代码中我们可以看到,只是在原来的基础上加了一个 useEffect 钩子,加了这个钩子过后可以使得打印结果是在组件渲染完成之后。
写过 vue 的小伙伴应该知道,每当我们要获取 DOM 时,是不是需要等到组件渲染完成过后再去获取,才能拿得到,所以当我们在 React 中获取 DOM 时,同理,至少得等到组件渲染完成过后吧。当状态,属性发生变化后,组件是否需要重新渲染,我们要想拿到新的状态,属性,那 useEffect 钩子就取到了大作用了。
总结
本节内容还是很简单的理解为:useEffect 钩子最主要的作用就是监听组件渲染完成后的一个回调函数。这样理解的话,在使用 useEffect 钩子就会更能得心应手。但是按我们之前的写法,会有这样一个问题,但凡是组件渲染重新渲染都会触发 useEffect 钩子,但是往往我们在开发时只需要监听特定状态或者属性变化时进行回调,我们下节将结合依赖数组对 useEffect 进行更进一步的学习。