【译】一文看懂 React useEffect hook 的用法

来源: Joseph Mawa. What is useEffect hook and how do you use it?.2020年6月30日html

目次

  • 介绍
  • useEffect hook 传递了哪些参数?
  • useEffect 的第一个参数
  • effect 的返回值
  • useEffect 的第二个参数
  • 传递一个函数做为依赖关系
  • 参考文献

这是我关于 react hook 系列的第三篇文章。若是你尚未看前两篇,请按照下面的连接来看。react

  1. What is useState hook and how do you use it?
  2. What is useReducer hook and how do you use it?

useEffect hook 简介

钩子是一个函数,它可让你在不编写ES6类的状况下使用状态和其余react特性。 useEffect钩子是react钩子API的一部分。若是你熟悉react生命周期,useEffect钩子至关于生命周期方法componentDidMountcomponentDidUpdatecomponentWillUnmount的组合。其实根据React文档中关于钩子的介绍useEffect钩子是为了解决ES6类组件的生命周期方法带来的一些挑战而开发的。因为本篇文章介绍的是什么是 effect hook ,以及它的使用方法,因此我就不说它的开发缘由了。你能够在这里看一下。 在React功能组件中,咱们在 useEffect 钩子里面执行有“反作用”的操做,好比从API中获取数据或者手动更新DOM。数组

useEffect hook 传递了哪些参数?

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);
复制代码

useEffect的第一个参数

第一个参数称为effect,是一个函数,它要么返回一个函数(称为cleanup),要么返回undefinedeffect在组件被挂载时(第一次渲染时)被执行,在后续的更新中是否被执行由做为第二个参数传递的依赖关系数组决定。dom

effect参数的返回值

在上一节中,咱们说过,useEffect的第一个参数是一个名为effect的函数。effect不须要参数,它必须返回一个函数或未定义的函数。若是它返回的是一个函数,那么返回的函数被称为cleanupcleanup在调用effect以前被执行(清理以前渲染的效果)。若是你对为何以及何时须要清理很好奇,能够看看React文档中的解释。因为effect返回的要么是函数,要么是undefined,因此没有cleanupeffect并很多见。ide

useEffect的第二个参数

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
复制代码

依赖关系能够是stateprops。须要注意的是,若是要在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的调用。

根据React文档中关于useEffect hook的部分

很难记住哪些props或state是由effect以外的函数使用的。这就是为何一般你会但愿在effect内部声明它所须要的函数。这样就能够很容易地看到该effect所依赖的组件做用域中的哪些值。
你也能够把函数移到effect内部,这样它就不须要在依赖列表中了。

参考文献

相关文章
相关标签/搜索