在我自己目前的開發中,很常使用到window這一個函數
window.addEventListener("scroll", function() {
console.log("scroll!")
});
但時常沒注意到位置,則會發生以下錯誤訊息
後來才發現造成這樣問題的主要原因,是我使用Nextjs它是一個具有Pre-rendering特性的React框架,
這也代表對於每一個頁面Nextjs都會嘗試先生成頁面HTML來獲得更好的SEO、使用體驗性...等,
在Nextjs生成頁面的過程中與Node.js呈現的關聯性導致該問題的發生,主軸也在於Node.js本身是沒有定義window這函數的,僅有window在瀏覽器中可用。
因此以下幾種為常見的處理方式
if(typeof window !== "undefined"){
//browser code
}
這個方法是當系統無法取得window函數時,進行額外處理,來避免系統報錯。
使用useEffect react hook主要是因為,僅會在渲染階段運行,所以它不會在服務器上面運作
import React,{ useEffect} from "react"
export default function Scroll(){
useEffect(function onFirstMount(){
function onScroll(){
console.log("scroll!")
}
window.addEventListener("scroll", onScroll)
},[])//此處空dependencies參數,代表僅在第一次掛載時,運作一次
return null;
}
使用dynamic imports(動態加載)並且設定ssr:false來禁用服務器渲染,藉此使得component(組件)不會在服務器端呈現出來
// 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 }
);
export default function Home() {
return (
<div style={{ minHeight: "1000px" }}>
<h1>Home</h1>
<Scroll />
</div>
);
}
PS.如果有需要進行全局加載組件,並且在頁面切換時不再進行mount/unmount(掛載/卸載),可以設定在 _app.js 中加載需要的組件