【Nextjs】useContextのデータをlocalStorageを使って永続化する

useContextはコンポーネント間のデータのやりとりにとても便利です。

useContextの実装記事はこちらです。

上記の記事では、stateだけで状態管理をするので、ブラウザが閉じる、リロードをするタイミングで状態は初期化されます。

ブラウザが閉じてもデータを永続化したい場合には、localStorageを利用します。

目次

Web Storage APIとは?

ブラウザがKey Value Pairでデータを保存できる仕組みになります。
とてもシンプルでstring型のみを格納でき、同期的な動作のみ許容します。

これらはWindowオブジェクトを通じて利用することができ、Storageインスタンスを生成することでデータの保存、参照、削除をすることができます。

cookieは最大サイズが4KBですが、localStorageでは最大10MBとかなりのデータが保存できるのも魅力的です。

Web Storage には2種類の仕組みがあります。

sessionStorage

ページセッションとして保存します。
ブラウザのリロードなどではデータを保持し続けます。
ブラウザーを閉じる、タブを閉じるなどでデータを破棄します。

localStorage

ブラウザのリロード、ブラウザを閉じる、タブを閉じるなどでもデータを保持し続けます。

公式サイト

公式により詳しく記載があります。参照してください。

useContextのstateをlocalStorageに保存する

useContextを実装した前回の記事にlocalStorageの実装を追加しました。
これで、localStorageに保存してデータを永続化することができます。

DataContext.Providerには、下記を行うstateと関数をセットします。

  • data : コンポーネント間のデータを保存
  • setData : stateの更新と、localStorageへの保存
  • initData : stateの初期化と、localStorageの削除

localStorageへ保存

setData関数を作成します。
localStorageはKeyValuePairでシンプルな実装が可能です。

window.localStorage.setItemでkeyをセットして文字列を渡すだけでデータ保存ができます。

配列やオブジェクトを保存したい時は、JSON.stringifyを使ってJSON文字列に変換してから保存します。

  const storeData = (data: DataType[]): void => {
    setData(data)
    window.localStorage.setItem(storageDataKeyName, JSON.stringify(data))
  }

DataContext.Providerのvalueで、setData関数とstoreData関数を紐づけます。

localStorageから削除

localStorage.removeItemにkeyをセットすることで対象のデータを削除します。

  const initData = (): void => {
    localStorage.removeItem(storageDataKeyName)
    setData([])
  }

全体コード

import { DataType, DataValuesType } from '@/types/Data'
import { createContext, useState, useContext, useEffect } from 'react'

const defaultProvider: DataValuesType = {
  data: [],
  setData: () => [],
  initData: () => void 0
}

const DataContext = createContext(defaultProvider)

const storageDataKeyName = 'local_storage_data_key'

export function useDataContext() {
  return useContext(DataContext)
}

export function DataProvider({ children }: { children: React.ReactNode }) {
  const [data, setData] = useState<DataType[]>([])

  const init = () => {
    const storedData = window.localStorage.getItem(storageDataKeyName)!

    if (storedData) {
      setData(JSON.parse(storedData))
    }
  }

  const initData = (): void => {
    localStorage.removeItem(storageDataKeyName)
    setData([])
  }

  const storeData = (data: DataType[]): void => {
    setData(data)
    window.localStorage.setItem(storageDataKeyName, JSON.stringify(data))
  }

  useEffect(() => {
    init()
  }, [])

  const value = {
    data,
    setData: storeData,
    initData: initData
  }

  return <DataContext.Provider value={value}>{children}</DataContext.Provider>
}

Summary

localStorageの利用はとても便利で、useContextのstateも永続化できます。

ただし、localStorageに保存されたデータは、あらゆるJavaScriptからアクセスすることができ、また削除処理を書かないとずっと残り続けるものになります。
このLocalStorageの性質を理解した上で、セキュリティを考慮しつつ、選択肢の一つとして検討が望ましいと思います。

よかったらシェアしてね!
目次