英文:
React: update state only once, when another state reaches certain value
问题
以下是您要翻译的代码部分:
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>
);
}
希望这对您有所帮助。如果您需要更多信息,请随时提问。
英文:
Here's my code 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>
);
}
I have some kind of async action wrapped into a custom hook useAsyncState
(simplified version of some real hook from my dependencies).
The problem is, I want to update value
only once, when async action turns into done
state.
However, changing state rerenders the component and since status
is still done
, value
changes again, leading to endless loop of decrementing.
Also, action can be triggered again and I want to decrement value, when it's done
again.
If I had an original Promise, I could do it in then
callback, but I have only a hook like this.
Also, using useEffect
delays value
update to the next render, so it takes two renders to show decremeneted value
. It's not a big deal, but it would be nice to do it in single render.
Is it ever possible to do it nice with such a custom hook? Or using raw Promises is the only way?
答案1
得分: 1
你可以使用功能性更新代替:
如果新状态是使用先前状态计算的,您可以将一个函数传递给setState。该函数将接收先前的值,并返回更新后的值。
useEffect(() => {
if (status === "done") {
setValue((prevValue) => prevValue - 1);
}
}, [status]);
英文:
You can use a Functional Update instead:
> If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value.
useEffect(() => {
if (status === "done") {
setValue((prevValue) => prevValue - 1);
}
}, [status]);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论