I have the following code and my goal is to update the value of text
on the button click after 2 seconds. While the console log is taking 2 seconds to print, the text
value is being updated right away. How can I make it to wait for 2 seconds to update the text
value?
function App() {
const [text, setText] = React.useState('Initial state');
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Changed state');
resolve('Changed state');
, 2000);
});
const handleOnClick = () => {
myPromise
.then(res => setText(res))
.catch(e => console.log(e));
};
return (
<p>{text}</p>
<button onClick={handleOnClick}>Click Me!</button>
);
}
CodePudding user response:
This happens because of the following:
- Your
App
component initially renders. mypromise
Promise
object gets initialized and therefore triggers its timeout.- When you press the button, 2000ms have already gone (from the render time) and therefore the
mypromise
has already resolved. - Your
then
function is immediately applied and callssetText
. setText
forces your component to re-render.- So the App function re-runs, and the
mypromise
object re-initializes forcing the setTimeout to re-trigger.
A way to fix it is to make your promise run lazily:
...
const myPromise = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Changed state");
resolve("Changed state");
}, 2000);
});
const handleOnClick = () => {
myPromise()
.then((res) => setText(res))
.catch((e) => console.log(e));
};
...
CodePudding user response:
export default function App() {
const [text, setText] = useState("Initial text");
const awaitPromise = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
const handleClick = async () => {
await awaitPromise(2000);
setText("Something else");
};
return (
<div className="App">
{text}
<button onClick={handleClick}>Click</button>
</div>
);
}