来源: Joseph Mawa. What is useEffect hook and how do you use it?.2020年6月30日html
这是我关于 react hook 系列的第三篇文章。若是你尚未看前两篇,请按照下面的连接来看。react
钩子是一个函数,它可让你在不编写ES6类的状况下使用状态和其余react特性。 useEffect
钩子是react钩子API的一部分。若是你熟悉react生命周期,useEffect
钩子至关于生命周期方法componentDidMount
、componentDidUpdate
和componentWillUnmount
的组合。其实根据React文档中关于钩子的介绍,useEffect
钩子是为了解决ES6类组件的生命周期方法带来的一些挑战而开发的。因为本篇文章介绍的是什么是 effect hook ,以及它的使用方法,因此我就不说它的开发缘由了。你能够在这里看一下。 在React功能组件中,咱们在 useEffect
钩子里面执行有“反作用”的操做,好比从API中获取数据或者手动更新DOM。数组
useEffect
是一个接受两个参数的函数。传递给useEffect
的第一个参数是一个名为effect
的函数(你能够猜到为何这个钩子叫useEffect
),第二个参数(是可选的)是一个存储依赖关系的数组。下面是它的使用说明。markdown
import React, { useEffect } from "react";
import { render } from "react-dom";
const App = props => {
useEffect(() => {
console.log("Effect has been called");
}); //Second argument to useEffect has been omitted
return <h1> Hello world! </h1>;
};
const root = document.getElementById("root");
render(<App />, root);
复制代码
第一个参数称为effect
,是一个函数,它要么返回一个函数(称为cleanup
),要么返回undefined
。effect
在组件被挂载时(第一次渲染时)被执行,在后续的更新中是否被执行由做为第二个参数传递的依赖关系数组决定。dom
effect
参数的返回值在上一节中,咱们说过,useEffect
的第一个参数是一个名为effect
的函数。effect
不须要参数,它必须返回一个函数或未定义的函数。若是它返回的是一个函数,那么返回的函数被称为cleanup
。cleanup
在调用effect
以前被执行(清理以前渲染的效果)。若是你对为何以及何时须要清理很好奇,能够看看React文档中的解释。因为effect
返回的要么是函数,要么是undefined
,因此没有cleanup
的effect
并很多见。ide
useEffect
的第二个参数是一个依赖关系的数组。若是你想控制在挂载组件后何时执行effect
,那么就传递一个依赖关系数组做为第二个参数。依赖关系是指定义在useEffect
以外,但在useEffect
内部使用的值,好比。函数
function App(){
const[state, setState] = useState(0);
// state is defined here
useEffect(() => {
console.log(state);
//value of state is used here therefore must be passed as a dependency
}, [state])
}
复制代码
React会比较依赖关系的当前值和以前渲染的值。若是它们不同,就会调用effect
。 这个参数是可选的。若是省略它,effect
将在每次渲染后被执行。若是你想让effect
只在第一次渲染时执行,你能够传递一个空数组。oop
useEffect(() => {
console.log("Effect has been called");
}, []) // Empty array as dependency, useEffect is invoked once
复制代码
依赖关系能够是state
或props
。须要注意的是,若是要在useEffect内部使用任何定义在useEffect
以外、且在组件内部的值,则必须将其做为依赖关系传递。这一点将在下面进行说明。fetch
function App(props) {
const [count, setCount] = React.useState(1);
// count and setCount are defined inside component(App) but outside useEffect
useEffect(() => {
//count is being used inside useEffect. Therefore must be passed as dependency.
console.log(count);
}, [count])
}
复制代码
你可能想知道,若是你在useEffect
以外定义了一个函数,而后在effect
里面调用它,你须要把它做为一个依赖关系传递给它吗? 举个例子。ui
function App(props){
const [data, setData] = useState(null);
const fetchData = () => {
//fetch some data
}
useEffect(() => {
fetchData(); //Invoked inside useEffect
}, [fetchData])
}
复制代码
不建议像上面这样,在外面定义一个函数,而后在effect
里面调用它。上面的状况会致使每次渲染都会调用fetchData
,由于传递的依赖是一个函数,而函数是对象。React会比较上一次和当前渲染的fetchData
,二者是不同的,所以会触发对effect
的调用。
很难记住哪些props或state是由effect以外的函数使用的。这就是为何一般你会但愿在effect内部声明它所须要的函数。这样就能够很容易地看到该effect所依赖的组件做用域中的哪些值。
你也能够把函数移到effect内部,这样它就不须要在依赖列表中了。