admin管理员组文章数量:1426086
I'm trying to render a loading message after 1.5 seconds of waiting, if the thing is still loading:
useEffect(() => {
setTimeout(() => {
if (loading) setSleepMessage("The server seems to be sleeping. Waking it up, wait a second...");
}, 1500);
}, [loading]);
The variable loading
is a boolean in state returned by an Apollo hook, and setSleepMessage
is hooked to state too:
import { useQuery } from "@apollo/client";
import React, { useState, useEffect } from "react";
// ...
const [ sleepMessage, setSleepMessage ] = useState<string>();
const { data , loading } = useQuery(SOME_QUERY);
// ...
For some reason my logic fails here; the sleep message is rendered after 1.5 seconds no matter whether loading
has changed from true
to false
at that point. Why is this? Is its value in setTimeout
evaluated right away even though the function is to be executed after the timer expires? Or am I missing something else here?
I'm trying to render a loading message after 1.5 seconds of waiting, if the thing is still loading:
useEffect(() => {
setTimeout(() => {
if (loading) setSleepMessage("The server seems to be sleeping. Waking it up, wait a second...");
}, 1500);
}, [loading]);
The variable loading
is a boolean in state returned by an Apollo hook, and setSleepMessage
is hooked to state too:
import { useQuery } from "@apollo/client";
import React, { useState, useEffect } from "react";
// ...
const [ sleepMessage, setSleepMessage ] = useState<string>();
const { data , loading } = useQuery(SOME_QUERY);
// ...
For some reason my logic fails here; the sleep message is rendered after 1.5 seconds no matter whether loading
has changed from true
to false
at that point. Why is this? Is its value in setTimeout
evaluated right away even though the function is to be executed after the timer expires? Or am I missing something else here?
3 Answers
Reset to default 2You didn't clear the previous timeout.
useEffect(() => {
const timeoutId = setTimeout(() => {
if (loading) setSleepMessage("The server seems to be sleeping. Waking it up, wait a second...");
}, 1500);
return () => clearTimeout(timeoutId);
}, [loading]);
You need to clean up your effects by returning a function to clear the timeout. I suggest also only initiating the timeout if loading
is true.
useEffect(() => {
let timerId;
if (loading) {
timerId = setTimeout(() => {
setSleepMessage(
"The server seems to be sleeping. Waking it up, wait a second..."
);
}, 1500);
}
return () => clearTimeout(timerId);
}, [loading]);
Firstly, the query is loading so the value of loading
is true, the setTimeout will be put into JS call stack and keep the value of loading
is true, after 1,5s it is put into task queue. After some ticks, the call stack is empty, it will put the callback function inside setTimeout back to callstack and setSleepMessage
is executed. So that why the sleep message is rendered after 1.5 seconds no matter whether loading is true or false. You should clearTimeout
in useEffect
to prevent this happens.
You can read more about event loop
in JS to dive deeper.
本文标签: javascriptHow to conditionally change state in useEffect after a delay in ReactStack Overflow
版权声明:本文标题:javascript - How to conditionally change state in useEffect after a delay in React? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745464981a2659493.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论