修復(fù)Next.js中window?is?not?defined方法詳解
引言
這個(gè)問題與Next.js的服務(wù)器端渲染有關(guān)。Next.js默認(rèn)會(huì)嘗試為您的網(wǎng)站使用SSR。這意味著,由于我們是在服務(wù)器上而不是在瀏覽器中,所以 "窗口 "對(duì)象并不存在。解決這個(gè)問題的方法是強(qiáng)迫Next.js在瀏覽器中運(yùn)行你的代碼,我將解釋如何做到這一點(diǎn)。
使用useEffect鉤子
該useEffect鉤子總是在瀏覽器中運(yùn)行,所以我們可以用它來確保我們的代碼只能從那里運(yùn)行。關(guān)于鉤子的快速入門知識(shí),請(qǐng)查看這篇文章。
下面是一個(gè)簡(jiǎn)單應(yīng)用的示例代碼,它將用戶最后一次訪問網(wǎng)站的時(shí)間存儲(chǔ)在本地存儲(chǔ)中。如果你不熟悉在React或Next.js中使用localStorage,可以看看我們這里的這個(gè)教程,它使用了類似的方法。這個(gè)方法是相同的,但有一個(gè)小的區(qū)別,那就是你可以在vanilla React組件的主體中使用localStorage,因?yàn)槟J(rèn)沒有SSR:
function updateLastSeen() { const lastSeen = window.localStorage.getItem('last-seen') ?? new Date(); window.localStorage.setItem('last-seen', new Date().toString()); return lastSeen; } function WindowPage() { const lastSeen = updateLastSeen(); return <div>Last Seen: {lastSeen}</div>; }
運(yùn)行這個(gè),我們得到這個(gè)你可能熟悉的錯(cuò)誤:
為了解決這個(gè)問題,讓我們引入一個(gè)自定義的鉤子,它涉及一個(gè) useEffect。
function useLastSeen() { const [lastSeen, setLastSeen] = useState(null); const retrieved = useRef(false); //To get around strict mode running the hook twice useEffect(() => { if (retrieved.current) return; retrieved.current = true; setLastSeen(updateLastSeen()); }, []); return lastSeen; }
我已經(jīng)把我們的邏輯移到了一個(gè)自定義的鉤子上,只是為了保持代碼的簡(jiǎn)潔?,F(xiàn)在隨著我們代碼的改變,代碼將只在鉤子運(yùn)行時(shí)運(yùn)行,也就是在客戶端。
然后我們可以將我們的組件更新為。
function WindowPage() { const lastSeen = useLastSeen(); return ( <div> Last Seen: {lastSeen} </div> ); }
這段代碼更簡(jiǎn)潔,而且由于 useEffect里面的鉤子只在客戶端運(yùn)行,我們的錯(cuò)誤就消失了
檢查窗口是否被定義
另一種方法是在我們運(yùn)行代碼之前簡(jiǎn)單地檢查窗口對(duì)象是否被定義。如果代碼在服務(wù)器上運(yùn)行,由于我們不在瀏覽器中,窗口對(duì)象就不存在。
我們不能使用與之前相同的例子,因?yàn)檫@種方法有一個(gè)關(guān)鍵的區(qū)別。因?yàn)槲覀儧]有等待組件的渲染,任何對(duì)頁面HTML的差異都會(huì)導(dǎo)致服務(wù)器端渲染的頁面版本與客戶端不同,我們會(huì)在Next.js中得到一個(gè)錯(cuò)誤。
在這個(gè)例子中,我們將為窗口對(duì)象添加一個(gè)事件監(jiān)聽器,以跟蹤頁面上的點(diǎn)擊和它們的位置。
const isBrowser = () => typeof window !== 'undefined'; //The approach recommended by Next.js function WindowPage() { const [lastClick, setLastClick] = useState(''); if (isBrowser()) { //Only add the event listener client-side window.addEventListener('click', (e) => setLastClick(`${e.pageX}, ${e.pageY}`) ); } return ( <div className="m-auto rounded bg-violet-600 p-10 font-bold text-white shadow"> Click at: {lastClick} </div> ); }
正如我們所看到的,代碼并沒有在服務(wù)器上運(yùn)行,所以Next.js現(xiàn)在很高興了
希望這兩種方法中的一種能幫助解決你的問題。我推薦第一種方法,因?yàn)樗w了大多數(shù)情況,而且你不必處理Next.js發(fā)現(xiàn)渲染不匹配的可能性。
以上就是修復(fù)Next.js中window is not defined方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Next.js window is not defined的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React hook 'useState' is calle
這篇文章主要為大家介紹了React hook 'useState' is called conditionally報(bào)錯(cuò)解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12react hooks實(shí)現(xiàn)防抖節(jié)流的方法小結(jié)
這篇文章主要介紹了react hooks實(shí)現(xiàn)防抖節(jié)流的幾種方法,文中通過代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-04-04react寫一個(gè)select組件的實(shí)現(xiàn)代碼
這篇文章主要介紹了react寫一個(gè)select組件的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04React中使用async validator進(jìn)行表單驗(yàn)證的實(shí)例代碼
react上進(jìn)行表單驗(yàn)證是很繁瑣的,在這里使用async-validator處理起來就變的很方便了,接下來通過本文給大家介紹React中使用async validator進(jìn)行表單驗(yàn)證的方法,需要的朋友可以參考下2018-08-08react中的forwardRef 和memo的區(qū)別解析
forwardRef和memo是React中用于性能優(yōu)化和組件復(fù)用的兩個(gè)高階函數(shù),本文給大家介紹react中的forwardRef 和memo的區(qū)別及適用場(chǎng)景,感興趣的朋友跟隨小編一起看看吧2023-10-10react-native動(dòng)態(tài)切換tab組件的方法
在APP中免不了要使用tab組件,有的是tab切換,也有的是tab分類切換.這篇文章主要介紹了react-native動(dòng)態(tài)切換tab組件的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-07-07React項(xiàng)目中報(bào)錯(cuò):Parsing error: The keyword &a
ESLint 默認(rèn)使用的是 ES5 語法,如果你想使用 ES6 或者更新的語法,你需要在 ESLint 的配置文件如:.eslintrc.js等中設(shè)置 parserOptions,這篇文章主要介紹了React項(xiàng)目中報(bào)錯(cuò):Parsing error: The keyword 'import' is reservedeslint的問題及解決方法,需要的朋友可以參考下2023-12-12React Native時(shí)間轉(zhuǎn)換格式工具類分享
這篇文章主要為大家分享了React Native時(shí)間轉(zhuǎn)換格式工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10