【问题标题】:How to check window.innerWidth in React/Gatsby before the website will render?如何在网站呈现之前检查 React/Gatsby 中的 window.innerWidth?
【发布时间】:2023-03-12 23:15:01
【问题描述】:

在我在 Gatsby 创建的网站上,我想在第一次渲染之前检查 DOM window.innerWidth 的大小。我想使用 innerWidth 的条件检查来决定网站应该如何呈现:作为桌面版或移动版。 一个简单的解决方法是在创建反应组件之前检查窗口的宽度,并在代码中进一步使用真/假值。它适用于开发版本,但... 情况是,在生产版本中,当我执行 gatsby build 时,控制台中出现错误:

failed Building static HTML for pages - 2.872s

 ERROR #95312 

"window" is not available during server-side rendering.

See our docs page for more info on this error: https://gatsby.dev/debug-html

> 30 |     const sizeOfWindow = window.innerWidth;

我已经尝试使用 componentWillMount,它工作正常,但已被弃用并标记为不安全。 如果我检查 componentDidMount 中的 window.innerWidth 没有正确渲染。

我的代码:

interface IndexPageState {
  isDesktop: boolean;
  windowWidth: number;
}

class IndexPage extends React.Component<any, IndexPageState> {
  constructor(props: any) {
    super(props);

    this.state = {
      windowWidth: 0,
      isDesktop: true,
    };
  }

  componentWillMount(): void {
    this.onResize();
  }

  onResize = () => {
    if (!(this.state.windowWidth >= 769)) {
      this.setState({ isDesktop: false });
    } else {
      this.setState({ isDesktop: true });
    }
  };

  componentDidMount = () => {
    this.setState({ windowWidth: window.innerWidth });
    if (!(this.state.windowWidth >= 769)) {
      this.setState({ isDesktop: false });
    } else {
      this.setState({ isDesktop: true });
    }
    window.addEventListener('resize', this.onResize);
  };

  componentWillUnmount = () => {
    window.removeEventListener('resize', this.onResize);
  };

  render() {
    const { isDesktop, windowWidth } = this.state;

    return (
      <>
        <SEO title="Home" />
        <div className={styles.App}>

【问题讨论】:

    标签: javascript reactjs mobile gatsby


    【解决方案1】:

    使用 Gatsby,您必须检查浏览器全局变量(如 documentwindow)的可用性,因为在您的代码编译并请求这些变量时,它们可能尚未声明/可用。

    来自Gatsby documentation

    您的一些代码引用了“浏览器全局变量”,例如 windowdocument。如果这是您的问题,您应该会看到上面的错误,例如 “未定义窗口”。要解决此问题,请找到有问题的代码并 a)在调用代码之前检查是否定义了窗口,因此 代码在 Gatsby 构建时不运行(参见下面的代码示例)或 b) 如果代码在 React.js 组件的渲染函数中,移动 将该代码转换为componentDidMount lifecycleuseEffect hook, 这确保代码不会运行,除非它在浏览器中

    因此,每次检查window 时,都必须添加:

        if(typeof window !== undefined){
         //your stuff
        }
    

    应用于您的代码:

      componentDidMount = () => {
        if(typeof window !== undefined){
          this.setState({ windowWidth: window.innerWidth });
          if (!(this.state.windowWidth >= 769)) {
            this.setState({ isDesktop: false });
          } else {
            this.setState({ isDesktop: true });
          }
          window.addEventListener('resize', this.onResize);
        }
      };
    
    
      componentWillUnmount = () => {
        if(typeof window !== undefined){
          window.removeEventListener('resize', this.onResize);
        }
    
       onResize = () => {
        if(typeof window !== undefined){ 
           if (!(this.state.windowWidth >= 769)) {
             this.setState({ isDesktop: false });
           } else {
           this.setState({ isDesktop: true });
           }
         }
       };
    };
    

    当然,上面的代码应该重构以避免条件的重复,例如在事件触发之前添加window条件。

    【讨论】:

      【解决方案2】:

      您可以在回调中包装获取窗口宽度,因此添加函数getWindowWidth 您将返回实际窗口宽度。

      【讨论】:

        【解决方案3】:

        检查window是这样定义的,然后尝试执行window.innerWidth

        componentDidMount() {
            if (typeof window !== 'undefined') {
                window.addEventListener('resize', this.onResize)
            }
        }
        componentWillUnmount() {
            if (typeof window !== 'undefined') {
                window.removeEventListener('resize', this.onResize)
            }
        }
        

        【讨论】:

        • 您也可以check this 了解如何检查window 是否已定义。
        猜你喜欢
        • 2020-10-25
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        • 2021-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-24
        相关资源
        最近更新 更多