大家好,上一篇文章我们学习了 State Hook 的基础用法,还没看的同学们,小编建议你先看下《 React Hooks 学习笔记 | State Hook(一)》这篇文章,今天我们一起来了解 useEffect Hook 的基础用法。
一、开篇
一般大多数的组件都需要特殊的操作,比如获取数据、监听数据变化或更改DOM的相关操作,这些操作被称作 “side effects(副作用)”。
在类组件中,我们通常会在 componentDidMount 和 componentDidUpdate 这两个常用的生命钩子函数进行操作,这些生命周期的相关方法便于我们在合适的时机更加精确的控制组件的行为。
这有一个简单的代码示例,页面加载完成后,更改页面的标题
componentDidMount() {
document.title = this.state.name + " from " + this.state.location;
}
当你尝试更改标题对应的状态值时,页面的标题不会发生任何变化,你还需要添加另一个生命周期的方法 componentDidUpdate() ,监听状态值的变化重新re-render,示例代码如下:
componentDidUpdate() {
document.title = this.state.name + " from " + this.state.location;
}
从上述代码我们可以看出,要实现动态更改页面标题的方法,我们需要调用两个生命钩子函数,同样的方法写两遍。但是我们使用 useEffect Hook 函数,就能解决代码重复的问题,示例代码如下:
import React, { useState, useEffect } from "react";
//...
useEffect(() => {
document.title = name + " from " + location;
});
可以看出,使用 useEffect Hook ,我们就实现了两个生命周期函数等效的目的,节省了代码量。
二、添加清除功能
还有一个类组件的例子,在某些情况下,你需要在组件卸载(unmounted)或销毁(destroyed)之前,做一些有必要的清除的操作,比如timers、interval,或者取消网络请求,或者清理任何在componentDidMount()中创建的DOM元素(elements),你可能会想到类组件中的 componentWillUnmount()这个钩子函数,示例代码如下:
import React from "react";
export default class ClassDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
resolution: {
width: window.innerWidth,
height: window.innerHeight
}
};
this.handleResize = this.handleResize.bind(this);
}
componentDidMount() {
window.addEventListener("resize", this.handleResize);
}
componentDidUpdate() {
window.addEventListener("resize", this.handleResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
}
handleResize() {
this.setState({
resolution: {
width: window.innerWidth,
height: window.innerHeight
}
});
}
render() {
return (
<p>
<h3>
{this.state.resolution.width} x {this.state.resolution.height}
</h3>
</p>
)
}
}
上面的代码将显示浏览器窗口的当前分辨率。当你调整窗口大小,您应该会看到自动更新窗口的宽和高的值,同时我们又添加了组件销毁时,在 componentWillUnmount() 函数中定义清除监听窗口大小的逻辑。
如果我们使用 Hook 的方式改写上述代码,看起来更加简洁,示例代码如下:
import React, { useState, useEffect } from "react";
export default function HookDemo(props) {
...
const [resolution, setResolution] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => {
setResolution({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener("resize", handleResize);
// return clean-up function
return () => {
document.title = 'React Hooks Demo';
window.removeEventListener(