reactjs - 如何将窗口调整大小事件监听器值设置为 react 状态?

标签 reactjs next.js

这个问题很简单,但我可能忽略了很少一点。窗口屏幕大小由 PostLayout 组件监听。当窗口宽度小于 768px 时,我预计 isDesktopSize 为 false。我尝试了所有方法,例如在 setIsDesktopSize 中使用箭头函数、使用 true 或 false 中的文本作为状态值、使用回调方法等...但它不起作用。

PostLayout 分享如下:

import React, {useState,useEffect, useCallback} from 'react'
import LeftSideNavbar from './LeftSideNavbar'
import TopNavbar from './TopNavbar'

export default function PostLayout({children}) {
    const [isDesktopSize, setIsDesktopSize] = useState(true)

    let autoResize = () => {
        console.log("Desktop: " + isDesktopSize);
        console.log(window.innerWidth);
        if(window.innerWidth < 768 ){
            setIsDesktopSize(false)
        }else{
            setIsDesktopSize(true)
        }
    }

    useEffect(() => {
        window.addEventListener('resize', autoResize)
        autoResize();  
    }, [])

    return (
        <>
            <TopNavbar isDesktopSize={isDesktopSize}/>
            <main>
                <LeftSideNavbar/>
                {children}
            </main>
        </>  
    )
}

控制台日志分享如下:

Desktop: true
627

最佳答案

这可能会被提取到自定义 Hook 中。您需要解决一些问题:

  1. 现在您将状态默认为 true,但是当组件加载时,这可能不正确。这可能就是您在第一次执行 effect 时看到不正确的控制台日志的原因。准确计算初始状态可以避免出现卡顿/双重渲染。
  2. 您没有在卸载组件时断开调整大小监听器,这可能会导致在卸载后尝试在组件上设置状态时出错。

这是解决这些问题的自定义 Hook 示例:

function testIsDesktop() {
    if (typeof window === 'undefined') {
        return true;
    }
    return window.innerWidth >= 768;
}

function useIsDesktopSize() {
    // Initialize the desktop size to an accurate value on initial state set
    const [isDesktopSize, setIsDesktopSize] = useState(testIsDesktop);

    useEffect(() => {
        if (typeof window === 'undefined') {
            return;
        }

        function autoResize() {
            setIsDesktopSize(testIsDesktop());
        }

        window.addEventListener('resize', autoResize);

        // This is likely unnecessary, as the initial state should capture
        // the size, however if a resize occurs between initial state set by
        // React and before the event listener is attached, this
        // will just make sure it captures that.
        autoResize();

        // Return a function to disconnect the event listener
        return () => window.removeEventListener('resize', autoResize);
    }, [])

    return isDesktopSize;
}

然后要使用它,您的其他组件将如下所示(假设您的自定义 Hook 就在同一个文件中——尽管将它提取到一个单独的文件并导入它可能很有用):

import React, { useState } from 'react'
import LeftSideNavbar from './LeftSideNavbar'
import TopNavbar from './TopNavbar'

export default function PostLayout({children}) {
    const isDesktopSize = useIsDesktopSize();

    return (
        <>
            <TopNavbar isDesktopSize={isDesktopSize}/>
            <main>
                <LeftSideNavbar/>
                {children}
            </main>
        </>  
    )
}

编辑:我对此稍作修改,因此理论上它应该可以与服务器端渲染器一起使用,该渲染器将采用桌面大小。

关于reactjs - 如何将窗口调整大小事件监听器值设置为 react 状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68019102/

相关文章:

javascript - ReactJS | onClick 的 Typescript 类型。 `onclick does not exist on type` x`

javascript - 如何使用 webpack 转换和缩小单个文件?

reactjs - 当我们使用react/next时,为什么需要在docker-compose中添加volume选项?

jquery - 将 Owl Carousel 2 与 next.js 一起使用并使用react

next.js - 将 next 的输出文件夹从 "_next"重命名为 "next"

javascript - next.js 将 props 从 HOC 传递给子组件 getInitialProps

javascript - 在 React/Meteor 中使用外部脚本

reactjs - 继承ReasonReact中的Nextjs App组件(pages/_app.js)

javascript - google-map-react 使用多个标记使 map 居中

javascript - 如何使用 Next.js 检查自定义服务器中是否存在页面