useEffect 与 reactjs 中的 setTimeout

useEffect with setTimeout in reactjs

倒计时每 1 秒减 2。但是如果我清理 setTimeout,代码 运行 正确。谁能解释一下? 我的结果:https://www.youtube.com/watch?v=NUE-nSLJbiY

    const tabs = ['posts', 'comments', 'albums'];
    const [title, setTitle] = useState('');
    const [posts, setPosts] = useState([]);
    const [type, setType] = useState('posts');
    const [show, setShow] = useState(false);

    useEffect(() => {
        fetch(`https://jsonplaceholder.typicode.com/${type}`)
            .then(res => res.json())
            .then(post => {
                setPosts(post);
            })
    }, [type])
    useEffect(() => {
        document.title = title;
    })

    const [countdown, setCountdown] = useState(180);
    useEffect(() => {
        const id = setTimeout(() => {
            setCountdown(prev => prev - 1);
            console.log(countdown);
        }, 1000);
        // return () => {
        //     clearTimeout(id)
        // }
    })

在每个渲染器上使用 运行s。这意味着当每个值发生变化时,都会发生渲染,然后触发另一个效果。

这不是我们想要的。有几种方法可以控制副作用运行.

我们应该始终包含接受数组的第二个参数。我们可以选择将依赖项传递给此数组中的 useEffect。

如果你想在它的值更新后立即更改倒计时,你应该像这样向 useEffect 添加依赖项:

 useEffect(() => {
        const id = setTimeout(() => {
            setCountdown(prev => prev - 1);
            console.log(countdown);
        }, 1000);
        // return () => {
        //     clearTimeout(id)
        // }
    }, [countdown])

以上代码 运行s 在第一次渲染和任何时间倒计时值更改。事实上,当倒计时减少时,顶部的 useEffect 触发器也是如此。

  useEffect(() => {
        document.title = title;
    }) //has no dependency

然后文档标题被更改,导致另一个呈现。所以你处于一个循环中,导致倒计时值递减 2。