Search code examples
zustand

How do I persist Map and Sets in zustand?


I have a simple store for a set of strings, and methods to add and remove strings. However, when persisted the names are converted to JSON objects when saved and not converted back to Sets when read from local storage. The same will happen for Map objects.

I was able to convert to Sets previously using serialize and deserialize, but those methods are now deprecated.

import AsyncStorage from "@react-native-async-storage/async-storage"
import { create } from "zustand"
import { createJSONStorage, persist } from "zustand/middleware"

interface Store {
    names: Set<string>
    addName: (name: string) => void
    removeName: (name: string) => void
}

export const useStore = create<Store>()(
    persist(
        (set) => {
            return {
                names: new Set(),
                addName: (name: string) => {
                    set((state) => {
                        const names = new Set(state.names)
                        names.add(name)
                        return { names }
                    })
                },
                removeName: (name: string) => {
                    set((state) => {
                        const names = new Set(state.names)
                        names.delete(name)
                        return { names }
                    })
                }

            }
        },
        {
            name: "domain-storage",
            storage: createJSONStorage(() => AsyncStorage),     
        }
    )
)


Solution

  • You can now use Zustand’s storage prop to serialize and deserialize maps and sets:

    
    storage: {
        getItem: (name) => {
          const str = localStorage.getItem(name)
          return {
            state: {
              ...JSON.parse(str).state,
              transactions: new Map(JSON.parse(str).state.transactions),
            },
          }
        },
        setItem: (name, newValue) => {
          const str = JSON.stringify({
            state: {
              ...newValue.state,
              transactions: Array.from(newValue.state.transactions.entries()),
            },
          })
          localStorage.setItem(name, str)
        },
        removeItem: (name) => localStorage.removeItem(name),
      },
    

    See the Zustand documentation here, which describes the storage prop as the replacement for the deprecated serialize and deserialize:

    https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md#how-do-i-use-it-with-map-and-set