Window is not defined in NextJS React app?

2020-02-23 07:47发布

In my NextJS app I can't seem to access window

Unhandled Rejection (ReferenceError): window is not defined

componentWillMount() {
    console.log('window.innerHeight', window.innerHeight);
}

enter image description here

6条回答
Evening l夕情丶
2楼-- · 2020-02-23 07:58

With No SSR

https://github.com/zeit/next.js#with-no-ssr

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('../components/hello3'),
  { ssr: false }
)

function Home() {
  return (
    <div>
      <Header />
      <DynamicComponentWithNoSSR />
      <p>HOME PAGE is here!</p>
    </div>
  )
}

export default Home
查看更多
放荡不羁爱自由
3楼-- · 2020-02-23 07:59

componentWillMount() lifecycle hook works both on server as well as client side. In your case server would not know about window or document during page serving, the suggestion is to move the code to either

Solution 1:

componentDidMount()

Or, Solution 2

In case it is something that you only want to perform in then you could write something like:

componentWillMount() {
    if (typeof window !== 'undefined') {
        console.log('window.innerHeight', window.innerHeight);
    }
}
查看更多
Animai°情兽
4楼-- · 2020-02-23 08:03

If you use React Hooks you can move the code into the Effect Hook:

import * as React from "react";

export const MyComp = () => {

  React.useEffect(() => {
    // window is accessible here.
    console.log("window.innerHeight", window.innerHeight);
  });

  return (<div></div>)
}

The code inside useEffect is only executed on the client (in the browser), thus it has access to window.

查看更多
对你真心纯属浪费
5楼-- · 2020-02-23 08:09

In the constructor of your Class Component you can add

    if (typeof window === 'undefined') {
        global.window = {}
    }

Example:

import React, { Component } from 'react'

class MyClassName extends Component {

constructor(props){
    super(props)
    ...
    if (typeof window === 'undefined') {
        global.window = {}
    }

}

This will avoid the error (in my case the error would occur after I would click reload of the page)

查看更多
Explosion°爆炸
6楼-- · 2020-02-23 08:19

Other solution is by using process.browser to just execute your command during rendering in client side only.

if (process.browser) {
  // client-side-only code
}

查看更多
爱情/是我丢掉的垃圾
7楼-- · 2020-02-23 08:20

Move the code from componentWillMount() to componentDidMount():

componentDidMount() {
  console.log('window.innerHeight', window.innerHeight);
}

In NextJS, componentDidMount() is executed only the client where window and other browser specific APIs will be available. From the NextJS wiki:

Next.js is universal, which means it executes code first server-side, then client-side. The window object is only present client-side, so if you absolutely need to have access to it in some React component, you should put that code in componentDidMount. This lifecycle method will only be executed on the client. You may also want to check if there isn't some alternative universal library which may suit your needs.

Along the same lines, componentWillMount() will be deprecated in v17 of React so it effectively will be potentially unsafe to use in the very near future.

查看更多
登录 后发表回答