【问题标题】:Mutate multiple states from within useEffect causes react-hooks/exhaustive-deps warning从 useEffect 中改变多个状态会导致 react-hooks/exhaustive-deps 警告
【发布时间】:2020-01-18 09:42:55
【问题描述】:

我正在玩 React Hooks。单击按钮时,我想增加一个计数器。计数器递增后,应用程序不应允许进一步递增,直到 clicked 重置为 false。

我想出了这个:

function App() {
  const [counter, setCounter] = useState(0);
  const [clicked, setClicked] = useState(false);

  useEffect(() => {
    if (clicked) {
      setCounter(counter + 1);
      setTimeout(() => {
        setClicked(false);
      }, 2000);
    }
  }, [clicked]);

  return (
    <div className="App">
      <p>Clicked: {String(clicked)}</p>
      <p>Counter: {counter}</p>
      <button type="button" onClick={() => setClicked(true)}>
        Click me
      </button>
    </div>
  );
}

它确实有效。但是 React 抱怨以下警告:

React Hook useEffect 缺少一个依赖项:'counter'。任何一个 包含它或删除依赖数组。你也可以做一个 功能更新 'setCounter(c => ...)' 如果你只需要'counter' 'setCounter' 调用。 (react-hooks/exhaustive-deps)

当我将计数器添加到依赖项时,useEffect 将进入无限循环,因为 clicked 为真,并且 setCounter 是从 useEffect 中调用的。

我只希望计数器在 clicked 从 false 变为 true 时递增。如果依赖项列表仅包含 clicked,则此方法有效,但 React 会抱怨这一点。

亲自尝试:https://codesandbox.io/s/dreamy-shadow-7xesm

【问题讨论】:

  • 只是一个问题,setCounter(counter =&gt; counter + 1)这个有什么问题?
  • the application should not allow further increments until clicked is reset to false 这是什么时候发生的?是否需要超时请求?

标签: reactjs


【解决方案1】:

尝试将 setCounter(counter + 1) 替换为:

setCounter(counter => counter + 1)

就像警告所说的那样。应该解决。

【讨论】:

  • 谢谢克雷格。在 VS 代码中,警告实际上是在没有建议 setCounter(c => ..) 的情况下显示的,就像这样“React Hook useEffect has missing dependencies: 'foo' and 'bar'。要么包含它们,要么删除依赖数组 react-hooks/详尽的deps”在沙箱中但是解决方案已经在警告中,哈哈。
  • 只想说这个方法用于异步问题,而不是与变量依赖问题同步
  • 谢谢。我看到了警告和解决方案,但这个例子更清楚。
【解决方案2】:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [counter, setCounter] = useState(0);
  const [clicked, setClicked] = useState(false);

  useEffect(() => {
    if (clicked) {
      setClicked(false);
      setCounter(counter + 1);
    }
  }, [clicked, counter]);

  return (
    <div className="App">
      <p>Clicked: {String(clicked)}</p>
      <p>Counter: {counter}</p>
      <button type="button" onClick={() => setClicked(true)}>
        Click me
      </button>
    </div>
  );
}

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

如果您取消超时,您的无限循环问题将会消失(顺便说一句,它的用途是什么?)您是否尝试实现去抖动或节流?我可以编辑这个答案来实现你想要的

【讨论】:

  • 谢谢!您如何实现点击的去抖?
  • codesandbox.io/s/relaxed-bas-lnqql .. 从使用 useEffect 移动到 useCallback。您的 useEffect 仅触发一次,因为依赖项仅更改一次(第一次单击时:这是从 false 到 true 的设置单击)。
猜你喜欢
  • 2020-05-01
  • 2021-04-15
  • 2020-06-08
  • 2020-06-22
  • 2020-02-21
  • 2020-10-12
  • 1970-01-01
  • 2020-01-18
  • 2021-09-03
相关资源
最近更新 更多