在我使用Next.js应用时,似乎无法访问window
:
未处理的拒绝(ReferenceError):window未定义
componentWillMount() {
console.log('window.innerHeight', window.innerHeight);
}
在我使用Next.js应用时,似乎无法访问window
:
未处理的拒绝(ReferenceError):window未定义
componentWillMount() {
console.log('window.innerHeight', window.innerHeight);
}
另一种解决方案是使用process.browser
来仅在客户端渲染期间执行您的命令。
但是,process
对象已在Webpack5和NextJS中被弃用,因为它是一个仅针对后端的NodeJS变量。
因此,我们必须使用浏览器的window
对象。
if (typeof window !== "undefined") {
// Client-side-only code
}
另一种解决方案是使用 React Hook 替换 componentDidMount
:
useEffect(() => {
// Client-side-only code
})
typeof window !== "undefined"
,否则它就是在服务器端运行。 - Allwe如果你使用React Hooks,你可以将代码移动到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>)
}
useEffect
中的代码仅在客户端(浏览器)执行,因此它可以访问 window
。
[]
添加为依赖项。 - deowkcomponentWillMount()
移动到 componentDidMount()
:componentDidMount() {
console.log('window.innerHeight', window.innerHeight);
}
在Next.js中,componentDidMount()
仅在客户端执行,因为只有在客户端才能使用window
和其他特定于浏览器的API。来自Next.js wiki的说明如下:componentWillMount()
将在React的第17版中被弃用,因此在不久的将来使用它可能会不安全。没有SSR
https://nextjs.org/docs/advanced-features/dynamic-import#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
TypeError: Cannot call a class as a function
- Shahriar出现错误是因为在组件加载时,窗口还不可用。只有在组件挂载后才能访问窗口对象。
您可以创建一个非常有用的钩子来获取动态的window.innerHeight
或window.innerWidth
。
const useDeviceSize = () => {
const [width, setWidth] = useState(0)
const [height, setHeight] = useState(0)
const handleWindowResize = () => {
setWidth(window.innerWidth);
setHeight(window.innerHeight);
}
useEffect(() => {
// component is mounted and window is available
handleWindowResize();
window.addEventListener('resize', handleWindowResize);
// unsubscribe from the event on component unmount
return () => window.removeEventListener('resize', handleWindowResize);
}, []);
return [width, height]
}
export default useDeviceSize
使用案例:
const [width, height] = useDeviceSize();
global?.window && window.innerHeight
使用运算符?.
非常重要,否则构建命令可能会崩溃。
componentWillMount()
生命周期钩子函数同时适用于服务器端和客户端。在您的情况下,在页面服务期间,服务器将不知道关于window
或document
的任何信息,建议将代码移至以下位置之一:
解决方案1:
componentDidMount()
或者,解决方案2
如果你只想在某个情况下执行某些操作,可以编写类似以下内容的代码:
componentWillMount() {
if (typeof window !== 'undefined') {
console.log('window.innerHeight', window.innerHeight);
}
}
有点晚了,但是你也可以考虑使用来自next
的动态导入(Dynamic Imports)来关闭该组件的SSR
。
你可以将该组件的导入封装在一个动态函数中,然后使用返回值作为实际组件。
import dynamic from 'next/dynamic'
const BoardDynamic = dynamic(() => import('../components/Board.tsx'), {
ssr: false,
})
<>
<BoardDynamic />
</>
ssr
而不是SSR
。 - Barry Michael DoyleBest solution ever
import dynamic from 'next/dynamic';
const Chart = dynamic(()=> import('react-apexcharts'), {
ssr:false,
})
在你的类的构造函数中,你可以添加Component
if (typeof window === 'undefined') {
global.window = {}
}
例子:
import React, { Component } from 'react'
class MyClassName extends Component {
constructor(props){
super(props)
...
if (typeof window === 'undefined') {
global.window = {}
}
}
这样做可以避免错误(在我的情况下,错误会在我点击页面重新加载后出现)。
global
的文档吗? - Jayenglobal.window
不会像浏览器环境中提供的实际 window
对象一样运行。 - juliomalves
componentDidMount()
中,该方法仅在客户端执行,因此可以使用window
。此外,componentWillMount()
在v17中已被弃用。https://github.com/zeit/next.js/wiki/FAQ#i-use-a-library-which-throws-window-is-undefined - Alexander Staroselsky