【问题标题】:how to detect window is loaded in react如何检测窗口是否加载到反应中
【发布时间】:2022-01-13 16:23:13
【问题描述】:

这几天我一直在尝试解决这个问题,但似乎无法让它发挥作用。

首先,如果客户端以移动或桌面格式查看,我有一个自定义挂钩。

看起来像这样:

import { useState, useEffect } from "react";

function getWindowDimensions() {
  if (typeof window !== "undefined") {
    const { innerWidth: width, innerHeight: height } = window;
    console.log("defined");
    console.log(width < 768);
    return width < 768 ? true : false;
  }
  console.log("undefined");
  return true;
}

export default function useWindowDimensions() {
  const [windowDimensions, setWindowDimensions] = useState(
    getWindowDimensions()
  );
  function handleResize() {
    setWindowDimensions(getWindowDimensions());
  }
  useEffect(() => {
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return windowDimensions;
}

现在我正在尝试使用它来在我的网站上的页脚或页眉样式交互之间切换:

import useWindowDimensions from "hooks/useWindowDimensions";
import React, { useEffect } from "react";
import Footer from "./Footer";
import Header from "./Header";

export default function Shim(props) {
  const isMobile = useWindowDimensions();

  return (
    <div>
      {!isMobile && <Header {...props} />}
      {isMobile && <Footer {...props} />}
    </div>
  );
}

我希望这可以完美运行,但是看起来好像在 typeof window === "undefined" 时设置了初始值,因此,移动视图以桌面大小呈现(如果我在网站已加载,它按预期工作。)有人愿意帮助我如何让它正常工作吗?

谢谢!

【问题讨论】:

    标签: javascript reactjs react-native react-hooks window


    【解决方案1】:

    我用这个上下文 api 钩子解决了同样的问题。

    import React, { createContext, useContext, useEffect, useState } from 'react';
    
    export const SizeContext = createContext();
    
    const SizeContextProvider = ({ children }) => {
        const [width, setWidth] = useState(window.innerWidth);
        const [isMobile, setIsMobile] = useState(true);
        const [isDesktop, setIsDesktop] = useState(true);
    
        function debounce(fn, ms) {
            let timer;
            return () => {
                clearTimeout(timer);
                timer = setTimeout(() => {
                    timer = null;
                    fn.apply(this, arguments);
                }, ms);
            };
        }
    
        useEffect(() => {
            const debouncedHandleResize = debounce(() => {
                setWidth(window.innerWidth);
            }, 0);
    
            window.addEventListener('resize', debouncedHandleResize);
    
            return () => {
                window.removeEventListener('resize', debouncedHandleResize);
            };
        });
    
        useEffect(() => {
            if (width <= 575) {
                setIsMobile(true);
                setIsDesktop(false);
            } else if (width >= 576 && width < 767) {
                setIsMobile(true);
                setIsDesktop(false);
            } else if (width >= 768 && width < 991) {
                setIsMobile(false);
                setIsDesktop(true);
            } else if (width >= 992 && width < 1199) {
                setIsMobile(false);
                setIsDesktop(true);
            } else {
                setIsMobile(false);
                setIsDesktop(true);
            }
        }, [width]);
    
        return (
            <SizeContext.Provider value={{ width, isDesktop, isMobile }}>
                {children}
            </SizeContext.Provider>
        );
    };
    
    export const useSizeContext = () => useContext(SizeContext);
    
    export default SizeContextProvider;
    

    import context api 使用任何组件。

    const App = () => {
      return (
        <SizeContextProvider>
          <Device />
        </SizeContextProvider>
      )
    }
    

    这里设备组件使用Context Api

    const Device = () => {
        const { isMobile, isDesktop } = useSizeContext();
    
        return (
            <div>
                {isMobile && <h1> Small Device </h1>}
                {isDesktop && <h1> Largest Device </h1>}
            </div>
        );
    }
    

    【讨论】:

    • 感谢您的回复!我目前在您的设置中收到此错误响应:TypeError: Cannot destructure property 'children' of 'undefined' as it is undefined. 3 | export const SizeContext = createContext(); 4 | &gt; 5 | const SizeContextProvider = ({ children }) =&gt; { | ^ 6 | const [width, setWidth] = useState(window.innerWidth); 7 | const [isMobile, setIsMobile] = useState(true); 8 | const [isDesktop, setIsDesktop] = useState(true);您对如何解决此问题有任何建议吗?
    • 对不起,我忘记包装上下文 api,它显示错误。请遵循此代码。请包装上下文 api app.js 并使用您的组件 js &lt;SizeContextProvider&gt; &lt;ComponentHere /&gt; &lt;/SizeContextProvider&gt; 现在它可以工作了。
    • 明白了。现在唯一的问题是我收到“未定义窗口错误”。所以我添加了一个 typeof window === "undefined" ? 1500 : window.innerHeight 在宽度线上,这解决了这个问题。这是您推荐的解决方案吗?非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    • 2010-10-02
    • 2021-11-28
    • 2011-09-19
    • 1970-01-01
    • 2011-10-30
    相关资源
    最近更新 更多