【问题标题】:React linter suggesting to wrap constant array with useMemo inside useEffect react-hooks/exhaustive-deps warningReact linter 建议在 useEffect react-hooks/exhaustive-deps 警告中使用 useMemo 包装常量数组
【发布时间】:2022-02-14 20:32:08
【问题描述】:

React linter 发出警告:

'someUnsharingArray' 数组使 useEffect Hook(在第 42 行)的依赖关系在每次渲染时都发生变化。将它移到 useEffect 回调中。或者,在自己的 useMemo() Hook react-hooks/exhaustive-deps 中包装 'someUnchangArray' 的初始化

为什么? someUnchangingArray 是一个常数,不会改变,为什么 React linter 建议它会在每次渲染时触发 useEffect

export default function Component(
  const [initialized, setInitialized] = useState(false);
  const someUnchangingArray = ["1", ""];
  useEffect(() => {
    if (!initialized) {
      // do some iniitializing
      console.log(someUnchangingArray, initialized);
      setInitialized(true);
    }
  }, [someUnchangingArray, initialized]);
...

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    v-dom rerender 基本上意味着它将重新运行您的所有组件(功能)

    因此您将为每个渲染创建新的数组引用

    只需将常量移到外面

    const someUnchangingArray = ["1", ""];
    
    export default function Component(
      const [initialized, setInitialized] = useState(false);
      useEffect(() => {
        if (!initialized) {
          // do some iniitializing
          console.log(someUnchangingArray, initialized);
          setInitialized(true);
        }
      }, [someUnchangingArray, initialized]);
    ...
    

    或者无论出于何种原因它需要在里面(取决于你的状态),那么你需要 useMemo 钩子

    【讨论】:

      【解决方案2】:

      您的组件是在每次渲染时调用的函数。 这意味着在每次渲染时someUnchangingArray 将指向一个新创建的数组引用。 useEffect 将收到一个新的引用,并决定是时候调用它了。

      function render() {
        const someUnchangingArray = ["1", ""];
        return someUnchangingArray
      }
      
      console.log(render() === render()); // false

      这是一个插图:

      function Component() {
        const [counter, setCounter] = React.useState(0);
        const supposedlySomeUnchangingArray = ["1", ""];
        
        React.useEffect(() => {
          console.count('USE EFFECT HAS BEEN CALLED');
        }, [supposedlySomeUnchangingArray]);
        
        return (
          <div>
            {counter}
            <button onClick={() => setCounter(counter + 1)}>do something to rerender</button>
          </div>
        );
      }
      
      
      ReactDOM.render(<Component />, document.getElementById('root'));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
      
      
      <div id="root">
      </div>

      检查控制台,您会看到每次重新渲染时都会调用 useEffect。

      【讨论】:

        猜你喜欢
        • 2020-05-01
        • 2021-04-15
        • 2020-06-22
        • 2020-06-08
        • 2020-02-21
        • 2020-01-18
        • 2021-09-03
        • 1970-01-01
        • 2020-05-14
        相关资源
        最近更新 更多