簡體   English   中英

如何將窗口調整大小事件偵聽器值設置為 React State?

[英]How to set window resize event listener value to React State?

這個問題很簡單,但我可能忽略了很少一點。 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

這可能會被提取到自定義鈎子中。 您需要解決一些問題:

  1. 現在您默認狀態為true ,但是當組件加載時,這可能不正確。 這可能是您在第一次執行效果時看到不正確的控制台日志的原因。 准確計算初始狀態可以為您節省一些卡頓/雙重渲染。
  2. 當組件卸載時,您不會斷開調整大小偵聽器的連接,這可能會導致在組件卸載后嘗試設置組件狀態時出錯。

這是解決這些問題的自定義鈎子的示例:

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;
}

然后要使用它,您的其他組件將如下所示(假設您的自定義掛鈎只是在同一個文件中 - 盡管將其提取到單獨的文件並導入它可能很有用):

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>
        </>  
    )
}

編輯:我對此稍作修改,因此理論上它應該與服務器端渲染器一起使用,該渲染器將假定桌面大小。

試試這個,你將 isDesktopSizze 設置為'mobile',即 === true

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

我在 npm 上沒有找到這樣的包,我認為創建一個會很好: https ://www.npmjs.com/package/use-device-detect。 我認為它會幫助某人:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM