【问题标题】:useEffect has a missing dependencyuseEffect 缺少依赖项
【发布时间】:2020-03-24 14:38:09
【问题描述】:

我想在钩子中实现componentDidMount,我想为第一次渲染做一些事情ONLY,所以在useEffect中,我将依赖数组设置为空,但eslint有警告缺少依赖项。 如何解决?

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

const Child = ({ age }) => {
  useEffect(() => {
    console.log("simulate componentDidMount, age:", age);
  }, []);

  useEffect(() => {
    console.log('simulate componentDidUpdate, age:', age)
  }, [age])

  return <div>age: {age}</div>;
};

const App = () => {
  const [age, setAge] = useState(0);
  const handleOnClick = e => {
    e.preventDefault();
    setAge(a => a + 1);
  };
  return (
    <>
      <Child age={age} />
      <button onClick={handleOnClick}>INCREASE AGE</button>
    </>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

【问题讨论】:

    标签: reactjs react-hooks eslint


    【解决方案1】:

    您可以将第一个渲染存储在 ref 中,并在 isFirstRender.current 为 true 时执行您需要做的事情,这样您不需要添加任何东西,但 age 可以将 cDM 和 cDU 组合在一起,将生命周期存储在状态中对我来说没有意义。

    const Child = ({ age }) => {
      const isFirstRender = useRef(true);
    
      useEffect(() => {
        if (isFirstRender.current) {
          isFirstRender.current = false;
          console.log("simulate componentDidMount, age:", age);
          return
        }
        console.log('simulate componentDidUpdate, age:', age);
      }, [age]);
    
      return <div>age: {age}</div>;
    };
    

    如果你想重用它,你也可以将它提取到自定义钩子中

    const useIsFirstRender = () => {
      const isFirstRender = useRef(true);
    
      useEffect(() => {
        isFirstRender.current = false;
      }, []);
    
      return isFirstRender.current;
    };
    
    const Child = ({ age }) => {
      const isFirstRender = useIsFirstRender();
    
      useEffect(() => {
        if (isFirstRender) {
          console.log("simulate componentDidMount, age:", age);
          return;
        }
        console.log('simulate componentDidUpdate, age:', age)
      }, [age, isFirstRender]);
    
      return <div>age: {age}</div>;
    };
    

    【讨论】:

      【解决方案2】:

      它说依赖项丢失了,因为您确实在useEffect 中使用了age,即使它只是为了打印出来,所以eslint 可能认为您应该添加age 做依赖项列表。

      useEffect(() => {
          console.log("simulate componentDidMount, age:", age); //age is being used here
        }, []);
      

      【讨论】:

      • 如果我将age添加到依赖项中,稍后当age更新时,useEffect内部的函数将再次被调用。我想实现类似于componentDidMount 的东西,它只被调用一次
      • 我明白,但是如果你想在那个 useEffect 中打印年龄,同时仍然保留 componentDidMount,你必须忽略警告。
      • 你认为如果是第一次渲染,记录本地状态是否更好?
      • @HuanLi - 最好有本地状态来记录第一次渲染,在我看来不太复杂。您比 eslint 更了解代码的用途,只需抑制警告即可。我一直使用}, []); // eslint-disable-line
      【解决方案3】:

      如果你不想禁用 eslint,你可以这样做:

      const [component_mounted, set_component_mounted] = useState(false)
      
      useEffect(() => {
          if(!component_mounted) {
            // Use age here
            set_component_mounted(true)
          }
        }, [age, component_mounted, set_component_mounted])
      

      【讨论】:

      • 正确的代码只有一点,但这有多吵? (与 linting 评论相比)
      【解决方案4】:

      React 并不关心你如何使用状态。所以打印年龄与将年龄放在一些逻辑计算中没有区别。埃斯林特做得对。

      【讨论】:

      • 你不明白我的意思。我想在没有 eslint 警告的情况下实现 componentDidMount
      猜你喜欢
      • 2021-02-23
      • 2021-08-19
      • 2020-10-26
      • 2019-10-24
      • 2020-03-07
      • 2020-02-25
      • 2020-01-06
      相关资源
      最近更新 更多