ReactJS 使用 useState 双重渲染布尔状态

c13*_*137 5 javascript reactjs react-hooks

我只是在玩 ReactJS 并试图通过 useState 钩子找出一些奇怪的行为。

如果状态设置为与之前相同的原始值(布尔值),则不应重新渲染组件

const useScroll = ({positionToCross = 10}) => {

    const window = useWindow();
    const [isPositionCrossed, setIsPositionCrossed] = useState(window.scrollY > positionToCross);

    useEffect(() => {

        const onScroll = function (e) {

            window.requestAnimationFrame(function () {
                const lastKnownScrollPosition = window.scrollY;
                setIsPositionCrossed(lastKnownScrollPosition > positionToCross);
            });

        }

        window.addEventListener('scroll', onScroll);

        return () => {
            window.removeEventListener("scroll", onScroll)
        }

    }, []);


    console.log(`useScroll - render window.scrollY = ${window.scrollY.toFixed(0)} isPositionCrossed = `, isPositionCrossed)
    return {isPositionCrossed}
}
Run Code Online (Sandbox Code Playgroud)

这是控制台输出 - 您可以看到组件和钩子都以“true”渲染两次(滚动超过 100px 后)

"useScroll - render window.scrollY = 101 isPositionCrossed = ", true
"useScroll - render window.scrollY = 103 isPositionCrossed = ", true
Run Code Online (Sandbox Code Playgroud)

HDM*_*M91 1

如果您尝试在单击处理程序 setState 上使用简单的代码,并且单击两次并且在每个具有相同值的更新状态下,组件会再次重新渲染。\n正如反应文档所述:

\n
\n

如果将 State Hook 更新为与当前状态相同的值,React 将退出而不渲染子项或触发效果。(React 使用 Object.is 比较算法。)

\n

请注意,React 可能仍需要在退出之前再次渲染该特定组件。这不应该成为一个问题,因为 React 不会不必要地将 \xe2\x80\x9cdeeper\xe2\x80\x9d 放入树中。如果您\xe2\x80\x99在渲染时进行昂贵的计算,您可以使用useMemo对其进行优化。

\n
\n

我希望这篇文章github 讨论中的答案 可以帮助您理解为什么会发生这种情况

\n

还有其他相关主题,例如这篇文章这个

\n


归档时间:

查看次数:

732 次

最近记录:

3 年,11 月 前