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の性質を理解した上で、セキュリティを考慮しつつ、選択肢の一つとして検討が望ましいと思います。