一、简单介绍
useEffect又叫副作用钩子,是React-Hook中的一种,如果说useState获取的是数据和改变状态的方法,那么useEffect就相当于组件的生命周期componentDidMount和componentDidUpdate以及componentWillUnMount.
二、第一个参数
useEffect的第一个参数,可以理解为是在生命周期下我们想要对状态做的处理。
对于点击按钮count++练习,不用钩子代码如下:
class App extends Component{
constructor(props){
super(props)
this.state={
count:0
}
}
change(){
this.setState({
count:++this.state.count
})
}
render(){
return(
<div>
<Text></Text>
<p>{this.state.count}</p>
<button onClick={()=>{this.change()}}>Change</button>
</div>
)
}
componentDidMount(){
document.title="Count:"+this.state.count
}
componentDidUpdate(){
document.title="Count"+this.state.count
}
}
这里添加了两个生命周期方法,注意document.tittle的变化。下面改成Hook useState+useEffect的形式:
function Text() {
var [count,setCount]=useState(0)
useEffect(()=>{//副作用钩子
//相当于componentDidMount和componentDidUpdate两个组件
document.title="Count"+count
})
return(
<div>
<p>{count}</p>
<button onClick={()=>{setCount(++count)}}>Add</button>
</div>
)
}
class App extends Component{
constructor(props){
super(props)
this.state={
count:0
}
}
change(){
this.setState({
count:++this.state.count
})
}
render(){
return(
<div>
<Text></Text>
<p>{this.state.count}</p>
<button onClick={()=>{this.change()}}>Change</button>
</div>
)
}
// componentDidMount(){
// document.title="Count:"+this.state.count
// }
// componentDidUpdate(){
// document.title="Count"+this.state.count
// }
}
再次观察document.title就会发现和刚才的结果一样,说明useEffect相当于两个生命周期函数。
useEffect副作用钩子有两种情况,
1.无需清理的
2.需要清理的
所谓需不需要清理要看,你的组件卸载后是否对整个项目有影响,是否还有程序在运行。对于上面案例,在App组件中将Text组件卸载后将不再有相关程序运行说明此时的组件是无需清理的,而需要清理一般会发生在定时器上,如下情况(直接写hook版本,非hook版本的添加其实就是在componentWillUnMount生命周期函数中添加定时器);
function Text() {
var [count,setCount]=useState(0)
useEffect(()=>{//副作用钩子
//相当于componentDidMount和componentDidUpdate两个组件
document.title="Count"+count
var timer=setInterval(() => {
console.log("Text")
}, 1000);
return function(){
clearInterval(timer)
}
})
return(
<div style={{border:"1px solid black"}}>
<p>{count}</p>
<button onClick={()=>{setCount(++count)}}>Add</button>
</div>
)
}
class App extends Component{
constructor(props){
super(props)
this.state={
count:0
}
}
change(){
this.setState({
count:++this.state.count
})
}
render(){
return(
<div>
{/* <Text></Text> */}
{this.state.count%2==0?<Text></Text>:""}
<p>{this.state.count}</p>
<button onClick={()=>{this.change()}}>卸载Text</button>
</div>
)
}
// componentDidMount(){
// document.title="Count:"+this.state.count
// }
// componentDidUpdate(){
// document.title="Count"+this.state.count
// }
}
主要看useEffect传递的第一个参数:
初始状态(上面是Text组件),右边控制台一直打印:
点击卸载,后组件内部定时器被清除,不再打印(再次点击Text组件恢复):
所以从此处看出,一个useEffect代替了三个生命周期:componentDidMount,componentDidUpdate,componentWillUnMount.
三、第二个参数
又称为依赖项,即当前这个useEffect的处理,是想针对哪一个状态进行的,通常以数组形式传入。
例如Text组件要维护两种状态count和str,如果不添加依赖项,那么两种状态任何一个发生改变都会触发处理行为(即useEffect传入的第一个函数参数)添加依赖项如下代码,:
function Text() {
var [count,setCount]=useState(0)
var [str,setStr]=useState("ads")
useEffect(()=>{//副作用钩子
//相当于componentDidMount和componentDidUpdate两个组件
document.title="Count"+count+" "+str
// var timer=setInterval(() => {
// console.log("Text")
// }, 1000);
// return function(){
// clearInterval(timer)
// }
},[count])
return(
<div style={{border:"1px solid black"}}>
<p>{count}</p>
<button onClick={()=>{setCount(++count)}}>Add</button>
<p>{str}</p>
<button onClick={()=>{setStr("111111")}}>ChangeStr</button>
</div>
)
}