【问题标题】:ReactJS double render for a Boolean state with useStateReactJS 使用 useState 双重渲染布尔状态
【发布时间】:2021-12-31 18:03:45
【问题描述】:

我只是在玩 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}
}

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

"useScroll - render window.scrollY = 101 isPositionCrossed = ", true
"useScroll - render window.scrollY = 103 isPositionCrossed = ", true

【问题讨论】:

  • 你是在一个开启StrictMode的开发环境中运行的,在16.8.0以上的React版本中运行吗?在这种情况下,许多函数被有意调用两次以帮助调试副作用,但在生产构建中它们只被调用一次,正如您所期望的那样。
  • 我只是试图在我的应用程序中删除StrictMode,它的行为相同。 React 版本是17.0.2
  • 一般来说,“为什么 React 多次调用我的组件函数”是一个不必要的问题。 React 完全可以随意调用你的函数多次。这就是为什么函数应该是纯的(除了钩子)。

标签: javascript reactjs react-hooks


【解决方案1】:

如果您在单击处理程序 setState 上尝试 simple code 并且如果您单击两次并且在每个更新状态中具有相同的值,则组件再次重​​新渲染。 正如react doc 所说:

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

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

我希望this postgithub discussion 的回答能帮助您理解为什么会发生这种情况

还有其他相关主题,例如 this postthis one

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-07-22
  • 2020-07-18
  • 1970-01-01
  • 2020-06-13
  • 2022-11-06
  • 2017-11-11
  • 1970-01-01
相关资源
最近更新 更多