问题
在 Next 中直接使用 window/document 会报 ReferenceError: window is not defined
原因
原因其实也比较简单,由于 nextjs 是服务端渲染,它会预渲染页面后生成 HTML,然后再将其发送给客户端,因此在渲染时无法识别 window/document 浏览器的对象方法。
解决方法
1. 使用 useEffect
这个方案是依赖于 useEffect 在进行服务器端渲染时不运行 useEffet,window 将在挂载时触发,在 useEffect 中的语句意味着服务器永远不会执行它,客户端将在挂载后才执行它(document 同理)。
useEffect(() =,{
console.log(window.location)
window.addEventListener('scroll', function() {
console.log('srcoll')
})
},[])
2. 检查 window
这个方法比较简单粗暴,直接判断 window 是否存在再执行对应代码(document 同理)
const callback = () => {
if (typeof window !== 'undefined') {
console.log('window:', window);
}
};
3. 动态加载组件
使用动态导入和 srr: false 选项加载组件。这样,您的组件甚至不会在服务器端呈现
// components/Scroll.js
function onScroll() {
console.log('scroll!');
}
window.addEventListener('scroll', onScroll);
export default function Scroll() {
return null;
}
// pages/index.js
import dynamic from 'next/dynamic';
const Scroll = dynamic(
() => {
return import('../components/Scroll');
},
{ ssr: false },
);