reactjs React:当另一个状态达到某个值时,仅更新状态一次

m4pnthwp  于 2023-02-18  发布在  React
关注(0)|答案(1)|浏览(185)

这是我的代码https://codesandbox.io/s/heuristic-cannon-lvse23?file=/src/App.js

import { useEffect, useState } from "react";

import "./styles.css";

function useAsyncState() {
  const [status, setStatus] = useState("idle");

  function trigger(value) {
    setStatus(`sending ${value}`);
    setTimeout(function () {
      setStatus("done");
    }, 1500);
  }

  return [status, trigger];
}

export default function App() {
  const [value, setValue] = useState(0);
  const [status, trigger] = useAsyncState();

  useEffect(() => {
    if (status === "done") {
      setValue(value - 1);
    }
  }, [status, value]);

  return (
    <div className="App">
      <p>
        status: {status}
        <button onClick={() => trigger(value)}>send & decrement</button>
      </p>
      <p>
        value: {value}
        <button onClick={() => setValue(value + 1)}>increment</button>
      </p>
    </div>
  );
}

我将某种异步操作 Package 到了一个定制钩子useAsyncState中(来自我的依赖项的一些真实的钩子的简化版本)。
问题是,我只想更新value一次,当异步操作变成done状态时。
然而,改变状态重新呈现组件,并且由于status仍然是done,因此value再次改变,导致递减的无限循环。
此外,动作可以再次触发,我想递减值,当它再次done
如果我有一个原始的Promise,我可以在then回调中完成,但我只有这样的钩子。
另外,使用useEffect会延迟value更新到下一个渲染,所以需要两个渲染来显示减少的value。这不是什么大问题,但在单个渲染中完成它会很好。
有没有可能用这样一个自定义的钩子做得很好?或者使用原始的承诺是唯一的方法?

rqqzpn5f

rqqzpn5f1#

您可以改用功能更新:
如果新的状态是使用先前的状态计算出来的,你可以传递一个函数给setState。这个函数将接收先前的值,并返回一个更新的值。

useEffect(() => {
  if (status === "done") {
    setValue((prevValue) => prevValue - 1);
  }
}, [status]);

相关问题