ReferenceError: localStorage is not defined のエラーの解決方法

7月 7, 2022

エラーの内容

npm run buildを実行すると、エラーになってしまういました。(ビルドができない)
エラーの表示内容はすごく長いので割愛しますが、
ReferenceError: localStorage is not defined
という表示の後にずらーと長いエラー表示がされました。
localStorageの行をコメントアウトをすると、エラーが出なくなります。
でも、localStorageは使いたいという状況です。

npm run devの場合

Server Error
ReferenceError: localStorage is not definedThis error happened while generating the page. Any console logs will be displayed in the terminal window.
というエラーがブラウザに表示されます。

動作環境

next.js
typescript

2022年7月
$ npm list
├── @types/node@18.0.1
├── @types/react-dom@18.0.5
├── @types/react@18.0.14
├── eslint-config-next@12.2.0
├── eslint@8.19.0
├── next@12.2.0
├── react-dom@18.2.0
├── react@18.2.0
└── typescript@4.7.4

原因と解決方法

原因は、localStorageで、localStorageがウィンドウオブジェクトで定義されておらず、Next.jsがクライアントレンダリングの前にサーバーレンダリングを実行するため。???
例えば、以下のようにtryで囲んだら、buildは成功しました。
(よく見ると、エラーは出ているのですが、buildは成功するということです)

// これだとbuild時にエラー発生
localStorage.setItem('key', 'value')

// tryを使うとエラーが起きない
try{
  localStorage.setItem('key', 'value')
  console.log("OK")
} catch(e){
  console.log("エラー")
}

react.jsかnext.jsのバージョンによって基準が変わったのでしょうか?
next.jsが原因のようです。
if (typeof window !== 'undefined') {}で囲むと良い?

if (typeof window !== 'undefined') {
  localStorage.setItem('key', 'value')
}else{
  console.log("エラー2")
}

自分の場合、この状態でコードをnpm run buildすると、ビルドができましたが、npm run startでブラウザから確認してChromeの開発コンソールのconsoleタブで見ると、やはりデータが入っていません。
npm run devの場合は即反映されるので、便利ですね。

ChromeのApplicationタブのLocal Storageを見る

ApplicationタブのLocal Storageを見ると、reactのlocalStorageでsetしたデータが入っていました。
Chromeの開発者コンソール(F12 or fn + F12)の中のApplicationタブのLocal Storageの項目を見ればlocalStorageにセットしたを全て見ることができます。