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?