useEffect依赖触发器如何在React中起作用?

时间:2020-10-11 12:55:13

标签: reactjs react-hooks

我想了解3种有关useEffect和eslint的“为什么”以及有关useEffect定义何时触发的总体“方式”的案例。

问题在代码示例中作为注释。

Codesandbox

import React, { useEffect, useState, useCallback } from "react";
import ReactDOM from "react-dom";

function App() {
  // Case A
  // why eslint want a as dependensy if it works fine?
  const [a, setA] = useState(0);
  const [triggerA, setTriggerA] = useState(true);

  useEffect(() => {
    console.log("Case 1: useEffect a: " + a);
  }, [triggerA]);

  // Case B
  // why eslint want fnB as dependensy if it works fine?
  const [b, setB] = useState(0);
  const [triggerB, setTriggerB] = useState(true);

  const fnB = useCallback(() => {
    console.log("Case B: useCallback fnB b: " + b);
  }, [b]);

  useEffect(() => {
    fnB();
  }, [triggerB]);

  // Case C
  // why adding fnC function as dependensy trigger useEffect,
  // but adding setC is not?
  // how useEffect understand when to trigger?
  const [c, setC] = useState(0);
  const [triggerC, setTriggerC] = useState(true);

  const fnC = useCallback(() => {
    console.log("Case C: useCallback fnC c: " + c);
  }, [c]);

  // no trigger
  useEffect(() => {
    console.log("no triger");
    fnC();
    setC((v) => {
      console.log("useEffect setC: " + v);
      return v;
    });
  }, [setC]);

  // triger
  useEffect(() => {
    console.log("triger");
    fnC();
    setC((v) => {
      console.log("useEffect fnC: " + v);
      return v;
    });
  }, [fnC]);

  console.log("----");

  return (
    <>
      <button onClick={() => setA((v) => v + 1)}>Add 1 to A</button>
      <button onClick={() => setTriggerA((v) => !v)}>Trigger A</button>
      <div>A: {a}</div>
      <hr />
      <button onClick={() => setB((v) => v + 1)}>Add 1 to B</button>
      <button onClick={() => setTriggerB((v) => !v)}>Trigger B</button>
      <div>B: {b}</div>
      <hr />
      <button onClick={() => setC((v) => v + 1)}>Add 1 to C</button>
      <button onClick={() => setTriggerC((v) => !v)}>Trigger C</button>
      <div>C: {c}</div>
      <hr />
    </>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));

1 个答案:

答案 0 :(得分:1)

依赖关系数组是一个依赖关系数组,当从上一个渲染更改时,它将调用第一个参数中定义的效果函数。

简而言之,您在effect函数中使用的任何变量和函数都应位于依赖项数组中,因为该函数取决于它们,所以当两个值中的任何一个更改时,它都应重新运行。

  1. 因为您在useEffect中使用了a
  2. 因为您在useEffect中使用了fnB
  3. 因为在依赖项数组中缺少fnC
  4. setCuseState中的状态更新程序功能,对其引用永远不会更改,除非手动完成。

即使您没有定义依赖项或缺少某些依赖项,所有函数也都将起作用,唯一的问题是,如果任一个值更改都会导致许多错误,那么效果将不会重新运行。例如:-

const id = props.id;
const [idData, setIdData] = React.useEffect(null);

// doesn't run when id changes
React.useEffect(() => {
   async function callApiAndUpdateIdData {

  } 

  callApiAndUpdateIdData()
}, []);

// runs when id changes
React.useEffect(() => {
   async function callApiAndUpdateIdData {

  } 

  callApiAndUpdateIdData()
}, [id]);