简体   繁体   English

setInterval 和 setState 中的 useEffect 错误

[英]useEffect Bug in setInterval and setState

i have tried useEffect function of React我尝试过 React 的 useEffect function

useEffect(() => {
    setInterval(() => {
        const time =
            Date.parse(untilDeadline.deadline) - Date.parse(new Date());
        setuntilDeadline((prevValue) => {
            return {
                ...prevValue,
                seconds: Math.floor((time / 1000) % 60),
                minutes: Math.floor((time / 1000 / 60) % 60),
                hours: Math.floor((time / (1000 * 60 * 60)) % 24),
                days: Math.floor(time / (1000 * 60 * 60 * 24)),
            };
        });
    }, 1000);
}, []);

this was crashing without [] in the end why?这在没有 [] 的情况下崩溃到底为什么?

The reason it was crashing is because you never clean up the setInterval call.它崩溃的原因是因为您从未清理 setInterval 调用。 So, every time the component re-renders (via the setuntilDeadline call for instance), the effect would run again.因此,每次组件重新渲染时(例如通过 setuntilDeadline 调用),效果都会再次运行。 What the [] indicate is that the effect should only run on mount and then clean itself up on unmount (as it's an empty dependency array). [] 表明效果应该只在挂载时运行,然后在卸载时自行清理(因为它是一个空的依赖数组)。

Additionally, you should clean up the setInterval call regardless of the dependency array in order to make sure that you don't have memory leaks and other performance issues.此外,无论依赖数组如何,您都应该清理 setInterval 调用,以确保您没有 memory 泄漏和其他性能问题。

useEffect(() => {
    const intervalId = setInterval(() => {
        const time =
            Date.parse(untilDeadline.deadline) - Date.parse(new Date());
        setuntilDeadline((prevValue) => {
            return {
                ...prevValue,
                seconds: Math.floor((time / 1000) % 60),
                minutes: Math.floor((time / 1000 / 60) % 60),
                hours: Math.floor((time / (1000 * 60 * 60)) % 24),
                days: Math.floor(time / (1000 * 60 * 60 * 24)),
            };
        });
    }, 1000);
    return ()=>{
       clearInterval(intervalId);
    }
}, []);

The empty array says to only run this once.空数组表示只运行一次。 Otherwise it might cause an infinite loop of re-renders.否则可能会导致无限循环的重新渲染。

You need that to only run once, and passing an empty array tells useEffect that there are no dependencies for the useEffect hook so it doesn't need to rerun on each render, and a setInterval would cause a rerender.你需要它只运行一次,并且传递一个空数组告诉 useEffect 没有依赖于 useEffect 钩子,因此它不需要在每次渲染时重新运行,并且 setInterval 会导致重新渲染。

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument.如果你想运行一个效果并且只清理一次(在挂载和卸载时),你可以传递一个空数组([])作为第二个参数。 This tells React that your effect doesn't depend on any values from props or state, so it never needs to re-run.这告诉 React 你的效果不依赖于 props 或 state 的任何值,所以它永远不需要重新运行。 This isn't handled as a special case — it follows directly from how the dependencies array always works.这不是作为特殊情况处理的——它直接遵循依赖项数组的工作方式。

If you pass an empty array ([]), the props and state inside the effect will always have their initial values.如果传递一个空数组([]),则效果内的道具和 state 将始终具有其初始值。 While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often.虽然传递 [] 作为第二个参数更接近于熟悉的 componentDidMount 和 componentWillUnmount mental model,但通常有更好的解决方案来避免过于频繁地重新运行效果。 Also, don't forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem.另外,不要忘记 React 会延迟运行 useEffect 直到浏览器绘制完成,所以做额外的工作不是问题。

https://reactjs.org/docs/hooks-effect.html https://reactjs.org/docs/hooks-effect.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM