0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

atomWithStorageでMap型を扱う方法

Posted at

概要

atomWithStorageでMap型を扱う際に躓いたため実装方法をメモついでに記事にしました。

下記の実装ではローカルストレージへの書き込みやローカルストレージからのロードでエラーが出たり、うまく動作しませんでした。

const sampleAtom = atomWithStorage<SampleMap>(
  'sample_map',
  new Map(),
)

ローカルストレージはstringのみ扱えるためMap型の値をJSON形式の文字列としてローカルストレージに書き込み、ローカルストレージからのロードする際は文字列型からJSONに変換し、それをMap型に変換する必要がある。

正しい実装方法

atomWithStorageのstorageパラメータにカスタム関数を渡すことで解決する。

storage (optional): an object with the following methods:

getItem(key, initialValue) (required): Reads an item from storage, or falls back to ?the intialValue
setItem(key, value) (required): Saves an item to storage
removeItem(key) (required): Deletes the item from storage
subscribe(key, callback, initialValue) (optional): A method which subscribes to >external storage updates.

type SampleMapItem = {
  value1: string
  value2: number
}
type SampleMap = Map<string, SampleMapItem>


// Mapのシリアライズ・デシリアライズ
const serializeMap = (map: Map<string, SampleMapItem>) =>
  JSON.stringify(Array.from(map.entries()))
const deserializeMap = (str: string) => new Map(JSON.parse(str))

// localStorageにMapを保存するための関数
const localStorageWithMap = {
  getItem: (key: string, initialValue: SampleMap) => {
    const item = localStorage.getItem(key)
    return item ? deserializeMap(item) : new Map()
  },
  setItem: (key: string, newValue: SampleMap) => {
    localStorage.setItem(key, serializeMap(newValue))
  },
  removeItem: (key: string) => {
    localStorage.removeItem(key)
  },
}

// atomの定義
const sampleAtom = atomWithStorage<SampleMap>(
  'sample_map',
  new Map(),
  localStorageWithMap
)

最後に

jotaiはあまり詳しくないですが、おそらくこれがベストプラクティスだと思っています。
もし他の良い方法があれば教えていただければ幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?