写在前面
虽然拿React
写了很多项目,自己搭过也用过很多三方脚手架,比如Antd Pro
Arco Pro
TDesign Starter
再例如跨端的Taro
但是因为工期还有自身原因,一直没有时间去深入一下React
的各个Hooks
正好这次借着参加更文活动的机会激励一下自己可以每天下班空闲之余可以多读一些深入了解一些吧,如果正在读文章的你也和我类似的情况欢迎一起交流学习
先跑个项目吧
快速便捷直接使用create-react-app
create-react-app react-day1
cd react-day1
yarn
yarn start
哦!我的老伙计!看那,是熟悉的原子图标!!!让我们开始吧!
官方定义
use useEffect. The function passed to useEffect will run after the render is committed to the screen. Think of effects as an escape hatch from React’s purely functional world into the imperative world.
By default, effects run after every completed render, but you can choose to fire them only when certain values have changed.
翻译一下大概就是useEffect
默认会在函数组件运行并完成渲染后被触发传进来的effect
函数,当然我们也可以让他只在某些值发生改变的情况下触发effect
https://reactjs.org/docs/hooks-reference.html#useeffect
useEffect
此Hooks
拥有两个参数。第一个参数为一个函数effect
,在此函数内可以做一些渲染完成后的动作,同时也可以在内部return
一个函数作为当前函数组件销毁时的清理函数类似,第二个为一个数组deps
,当传递的数组为[]
空时useEffect
则只会在函数运行并渲染完后直接调用。但如果你往deps
参数数组中传递了一个或多个的时候,useEffect
将会在deps
依赖中的元素发生改变时触发effect
从而达到跟随props
或者state
更新而触发effect
来达到不同目的的情况
严格模式下重复执行
使用create-react-app
创建出来的应用默认会在入口处使用React.StrictMode
来创建App
,从而导致在React
版本大于18的项目中出现useEffect
调用两次的情况,此现象在生产模式下只会调用一次,如需关闭可以去掉React.StrictMode
直接render
用于DOM完成渲染之后
在日常开发中我们经常需要对Table
或者Profile
等等组件的数据进行初始化,这时候使用useEffect
会是一个不错的选择,例子如下
import React, { useEffect, useState } from 'react'
const fetchUserData = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({
id: 1,
userName: 'Gnod'
})
}, 1500)
})
}
const ChildrenA = () => {
const [profile, setProfile] = useState(null)
useEffect(() => {
fetchUserData().then(res => {
setProfile(res)
})
}, [profile])
return (
<div>
<div>
UserName: {profile && profile.userName || '-'}
</div>
</div>
)
}
export default ChildrenA
用于组件销毁时
此处类似于componentWillUnmount
生命周期,可用于在组件销毁时进行一些操作,比如清除Interval
或者发送埋点或者取消一些事件的订阅,例子如下
import React, { useEffect, useState } from 'react'
const ChildrenB = () => {
const [count, setCount] = useState(0)
useEffect(() => {
const timer = setInterval(() => {
setCount(old => old 1)
}, 100)
return () => {
clearInterval(timer)
}
}, [])
return (
<div>
<div>
Count: {count}
</div>
</div>
)
}
export default ChildrenB
上述代码在useEffect
被调用时创建了一个Interval
并在useEffect
提供的Destructor
在销毁时清理掉了Interval
弹出了提示
用于State或Props更新时
由于State
Props
更新时触发effect
的用法一致,所以就只拿state
来作为例子,这里我们做了一个简单的计数器然后来监听计数器的每一次更新
import React, { useEffect, useState } from 'react'
const ChildrenC = () => {
const [count, setCount] = useState(0)
useEffect(() => {
console.log('count updated', count)
}, [count])
return (
<div>
<div onClick={() => { setCount(count 1) }}>
Count: {count}
</div>
</div>
)
}
export default ChildrenC
观察控制台可以发现在每一次count
发生改变的时候useEffect
都帮我们调用了effect
函数从而在console
里面打印出了count updated: xxx
最后
这是写给自己的React巩固计划的第一篇,希望在下班空闲之余通过写作的方式可以更加深入了解React
各个方面的知识