useEffect 处理副作用 (生命周期钩子函数)
可以使得你在函数组件中执行一些带有副作用的方法,天哪,“副作用”(大脑中无数个????)。
每当 React组件更新之后,就会触发 useEffect,在第一次的render 和每次 update 后,useEffect都会触发,不用再去考虑“初次挂载”还是“更新”。React 保证了每次运行 effect 的同时,DOM 都已经更新完毕。
你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 这两个函数的组合。但是比
格式:
useEffect(回调函数,[依赖]); //在render之后触发useEffect,进一步调用回调函数
1、useEffect的无条件执行(只有一个参数),表示依赖所有的状态。
import React,{useState,useEffect} from 'react';
function App() {
const [count,setCount] = useState(0);
//useEffect:相当于 componentDidMount,componentDidUpdate
useEffect(()=>{
console.log("userEffect");
document.title = count;
});
return (
<div className="App">
<p>{count}</p>
<input type="button" value="测试" onClick={()=>{setCount(count+1)}} />
</div>
);
}
2、useEffect的条件执行(useEffect的第二个参数)
当useEffect只有一个参数时,会无条件执行,那么,当发送请求时(页面的初始数据来自后端),一旦把请求放在useEffect里,就会无休止的执行。因为,当请求的数据回来后,引起组件的更新,组件更新后,再次触发useEffect,再次发送请求,再次组件更新………………,陷入到了无限的死循环。怎么办呢?可以使用useEffect的第二个参数。
第二个参数表示:useEffect是否再次触发 是 依赖于某个状态的变化。当为空数组时,表示不会二次触发。即:componentDidMount时会触发,componentDidUpdate不会触发。
换种解释方式:
1、这是格式: useEffect(回调函数,依赖的数组)
2、数组里是回调函数是否执行的条件,(即:数组里的状态发生变化时,才调用回调函数)
3、如果是空数组,表示任何状态发生变化,都不会调用回调函数。相当于componentDidMount
如下代码,由于依赖是空,所以,useEffect只表示componentDidMount。
useEffect( async ()=>{
let data = await getBooks(); //发送请求的代码已经封装
setBooks(data);
},[]);
如下代码,表示componentDidMount,和 count变化后引起的componentDidUpdate。
useEffect( async ()=>{
let data = await getBooks(); //发送请求的代码已经封装
setBooks(data);
},[count]);
另外一个角度理解:
// 1、不写依赖(依赖所有的状态):等价于componentDidMount,componentDidUpdate
// 任何状态发生变化,都会调用useEffect的回调函数
// useEffect(()=>{
// console.log("useEffect");
// })
// 2、依赖count:当count发生变化时,调用useEffect的回调函数。
// 等价于componentDidMount,componentDidUpdate(count引起的)
// useEffect(()=>{
// console.log("useEffect");
// },[count])
//3、空依赖:没有依赖,
// 等价于componentDidMount
useEffect(()=>{
console.log("useEffect");
},[])
即:
// 2.1)、如果没有写第二个参数,表示依赖所有状态
// 2.2)、如果第二个参数是空数组,表示没有任何依赖。就相当于 componentDidMount
// 2.3)、如果第二个参数的数组里,写上了状态(如:count),那就表示依赖该状态(如:count)