useState() 未在 useEffect() 挂钩内更新

E M*_*ill 5 state reactjs react-redux react-hooks

我在更新 useEffect() 内部的 useState() 时遇到问题。我想我可能会遇到无限循环,并且无论我传入的布尔值如何,useState 都不会更新。它总是显示 false。

export const useAlert = () => {
  const action = useSelector(state => state.edit.action);

  const dispatch = useDispatch();

  const booleanA = true;

  const booleanB = false;

  const [isOverMax, setIsOverMax] = useState(false);
  const reset = () => {
    dispatch(resetEditAction());
  };

  useEffect(() => {
    setIsOverMax(booleanA || booleanB);
  }, isOverMax);

  return [isOverMax, reset];
};
Run Code Online (Sandbox Code Playgroud)

对于更多上下文,booleanAbooleanB是用其他代码动态生成的,但即使它们像上面那样被硬编码,也isOverMax只能是false. 即使两个布尔值都被硬编码为 true,我也永远无法获得真正的值。

Ren*_*ink 4

状态isOverMax源自booleanAbooleanB。因此,只要或改变,isOverMax就应该改变。您应该在依赖项数组中反映这一点。booleanAbooleanB

 useEffect(() => {
   setIsOverMax(booleanA || booleanB);
 }, [booleanA, booleanB]);
Run Code Online (Sandbox Code Playgroud)

这是工作示例。只需单击“显示代码片段”,然后单击“运行代码片段”

 useEffect(() => {
   setIsOverMax(booleanA || booleanB);
 }, [booleanA, booleanB]);
Run Code Online (Sandbox Code Playgroud)
const useAlert = () => {
  const [booleanA, setA] = React.useState(true);
  const [booleanB, setB] = React.useState(false);
  const [isOverMax, setIsOverMax] =React. useState(false);

  const reset = () => {
    setA(false);
    setB(false);
  };

  React.useEffect(() => {
    setIsOverMax(booleanA || booleanB);
  }, [booleanA , booleanB]);

  // just for testing
  const toggleA = () => {
    setA((a) => !a);
  }

   return [isOverMax, reset, toggleA];
};

const App = () => {
  const [alert, reset, toggleA]  = useAlert();
  return <div>
    isOverMax={"" + alert}<br/>
    <button onClick={() => toggleA()} >Toggle A</button>
    <button onClick={() => reset()} >Reset </button>
  </div>;
};

ReactDOM.render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)

由于状态booleanAbooleanB已经存在,因此当其中之一发生更改时,它们将触发重新渲染。因此你可以只返回计算结果isOverMax

const useAlert = () => {

   // ...
   return [booleanA || booleanB, reset];
}
Run Code Online (Sandbox Code Playgroud)

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)
const useAlert = () => {

   // ...
   return [booleanA || booleanB, reset];
}
Run Code Online (Sandbox Code Playgroud)

编辑

是否有关于何时不使用效果挂钩的一般准则,以便我不会开始将其扔到不重要的代码中?

不一定,但您应该阅读Hooks 规则。这些规则告诉您应该采取哪些措施来防止不可预测的行为。遗憾的是,他们没有解释该规则的原因,而这个问题是解释这一切的错误地方。因此,如果您还有问题,请提出另一个问题。