设置嵌套setTimeout中的状态错误

huangapple go评论71阅读模式
英文:

setting state in nested setTimeouts bug

问题

I'm trying to add JSX elements to a state array on a timer. So once the component is rendered, after 1200ms, a JSX element should be added to the array. 2 Seconds later, another JSX element should be added to the array.

The issue is, once the second setBlocks is called, the first JSX Element gets removed. Wondering if there is a way around this, or a better way to pull this off. Here is the useEffect:

  useEffect(() => {
    setTimeout(() => {
      setBlocks([...blocks, serverBlock]);
      setTimeout(() => {
        setBlocks([...blocks, commandBlock]);
      }, 2000);
    }, 1200);
  }, []);

And here is how I'm rendering the elements:
<div>{blocks.map((block) => block)}</div>

英文:

I'm trying to add JSX elements to a state array on a timer. So once the component is rendered, after 1200ms, a JSX element should be added to the array. 2 Seconds later, another JSX element should be added to the array.

The issue is, once the second setBlocks is called, the first JSX Element gets removed. Wondering if there is a way around this, or a better way to pull this off. Here is the useEffect:

  useEffect(() =&gt; {
    setTimeout(() =&gt; {
      setBlocks([...blocks, serverBlock]);
      setTimeout(() =&gt; {
        setBlocks([...blocks, commandBlock]);
      }, 2000);
    }, 1200);
  }, []);

And here is how I'm rendering the elements:
<div>{blocks.map((block) => block)}</div>

答案1

得分: 1

你应该传递一个更新函数给 setBlocks,以便根据实际的先前值更改状态。

还需要从 useEffect 返回一个清理函数,以在组件卸载时取消超时。

useEffect(() => {
	const id = setTimeout(() => {
	  setBlocks(prevBlocks => [...prevBlocks, serverBlock]);
	  setTimeout(() => {
		setBlocks(prevBlocks => [...prevBlocks, commandBlock]);
	  }, 2000);
	}, 1200);
	return () => clearTimeout(id);
}, []);
英文:

You should pass an updater function to setBlocks so you can change the state based on the actual previous value.

You also need to return a cleanup function from useEffect to cancel the timeout when the component is unmounted.

useEffect(() =&gt; {
	const id = setTimeout(() =&gt; {
	  setBlocks(prevBlocks =&gt; [...prevBlocks, serverBlock]);
	  setTimeout(() =&gt; {
		setBlocks(prevBlocks =&gt; [...prevBlocks, commandBlock]);
	  }, 2000);
	}, 1200);
	return () =&gt; clearTimeout(id);
}, []);

huangapple
  • 本文由 发表于 2023年5月15日 03:27:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76249323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定