在 React 中,function component 和 class component 相比较,function component 是没有生命周期的
我们可以用 useEffect
来代替在 class component 中,一些有关生命周期的操作
我们用一个例子来说明 useEffect
的一些用法和作用
首先有一个 Example 组件,组件里面有一个 button,当点击 button 的时候,可以进行计数
在这个组件里面还有两个 link,Index 和 List
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => { setCount(count + 1) }}>click me</button>
<Router>
<ul>
<li><Link to="/">Index</Link></li>
<li><Link to="/list/">Link</Link></li>
</ul>
<Route path="/" component={Index} exact></Route>
<Route path="/list/" component={List} exact></Route>
</Router>
</div>
)
}
export default Example;
function Index() {
return (
<p>this is Index</p>
)
}
function List() {
return (
<p>this is List</p>
)
}
现在页面上是这样子的

现在给 Index 和 list 分别加上 useEffect
function Index() {
useEffect(() => {
console.log("this is Index");
})
return (
<p>this is Index</p>
)
}
function List() {
useEffect(() => {
console.log("this is Link");
})
return (
<p>this is List</p>
)
}
当页面第一次渲染的时候

点击 Link

可以看出此时 useEffect
有类似 componentDidMount
的作用
现在点击两次 button

可以看到 “this is Link” 又多打印了两次,可以看出 useEffect
有类似 componentDidUpdate
的作用
注意:
- React 首次渲染和之后的每次渲染都会调用一遍
useEffect
函数,而componentDidMount
表示首次渲染,componentDidUpdate
表示更新导致的重新渲染 -
uesEffect
中定义的函数的执行不会阻碍浏览器更新视图,也就是说这些函数是异步执行的,但是componentDidMount
和componentDidUpdate
中的代码都是同步执行的
现在,我们给 useEffect
加上一个 return
函数
function Index() {
useEffect(() => {
console.log("this is Index");
return () => {
console.log("you have leaved Index");
}
})
return (
<p>this is Index</p>
)
}
function List() {
useEffect(() => {
console.log("this is Link");
return () => {
console.log("you have leaved Link");
}
})
return (
<p>this is List</p>
)
}
当初次渲染,然后点击 Link 的时候

再切换回 Index

可以看到在组件 unmount 的时候, useEffect
里面的 return
函数被触发了
所以 useEffect
也可以实现 componentWillUnmount
的功能
但是!
当我们点击 button 的时候

可以看到 useEffect
里面的 return
也执行了
但是我们不想让它执行,只是实现 componentWillUnmount
的功能
这时候可以设置 useEffect
的第二个参数
function Index() {
useEffect(() => {
console.log("this is Index");
return () => {
console.log("you have leaved Index");
}
}, [])
return (
<p>this is Index</p>
)
}
这时候点击 button

切换

关于 useEffect
的第二个参数
我们现在给 Example 加一个 useEffect
useEffect(()=>{
console.log(`useEffect=>You clicked ${count} times`)
return ()=>{
console.log('====================')
}
},[count])
第一次渲染的时候

点击 button 的时候

总结:
- 当没有
return
的时候- 第二个参数是副效应函数的依赖项,只有该变量发生变化的时候,副效应函数才执行
- 如果第二个参数是一个空数组,表明副效应参数没有任何依赖项,所以,副效应函数这时只会在组件加载进 DOM 后执行一次
- 当有
return
的时候,return
函数部分- 如果没有第二个参数,state 发生变化,组件 unmount 的时候会执行;
- 如果第二个参数是一个空数组,那么
return
部分和componentWillUnmount
效果是一样的 - 如果有依赖项,依赖项发生变化的时候,,
useEffect
第一个参数部分都会执行,并且return
函数先执行
网友评论