Unable to use zustand persist middleware
Asked Answered
L

3

8

I'm working on a react-native app and I'm getting below warning after adding persistent middleware.

[zustand persist middleware] Unable to update item 'todos', the given storage is currently unavailable.

here is the code.

import {devtools, persist} from 'zustand/middleware';

const todosStore = set => ({
  todos: [],
  addTodo: todo =>
    set(state => {
      return ({todos: [todo, ...state.todos]});
    }),
});

const useStore = create(
  devtools(
    persist(todosStore, {
      name: 'todos',
      getStorage: () => storage,
    }),
  ),
);

export default useStore;


Lyric answered 19/5, 2022 at 22:18 Comment(0)
T
9

The use of getStorage, inside persist middleware, now is deprecated. To solve this, you can just change by storage. It uses createJSONStorage that can be imported from zustand/middleware

From:

getStorage: () => AsyncStorage

To:

storage: createJSONStorage(() => AsyncStorage)
Toxicology answered 19/1, 2023 at 15:47 Comment(1)
Thanks. I'm using the latest version, and your answer is the correct one.Ogee
H
3

Use react-native-async-storage or any storage module which have getItem/setItem methods to store the data locally on react-native

import {devtools, persist} from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage'; <-- Add this

const todosStore = set => ({
  todos: [],
  addTodo: todo =>
    set(state => {
      return ({todos: [todo, ...state.todos]});
    }),
});

const useStore = create(
  devtools(
    persist(todosStore, {
      name: 'todos',
      getStorage: () => AsyncStorage, <--- Add This
    }),
  ),
);

export default useStore;
Hermosa answered 18/6, 2022 at 18:41 Comment(1)
This saved the day! Thanks!Sundog
T
1

Looking better at the MMKV and Zustand, if I'm not wrong, you can simply create a custom store like this:

I'm doing it for React Native, but there many other configs on zustand's page for other frameworks...

// MMKV.ts
import { MMKV } from 'react-native-mmkv';

const storage = new MMKV({
  // ... MMKV configs here ...
});

export default {
  setItem: (name: string, value: string) => storage.set(name, value),
  getItem: (name: string) => storage.getString(name) ?? null,
  removeItem: (name: string) => storage.delete(name)
};

At the persistency's configs object, you can do like this:

import { devtools, persist } from 'zustand/middleware';

// ... Store code here ...

const devtoolsConfig: DevtoolsOptions = {
  name: 'my-storage-name',
  enabled: process.env.NODE_ENV === 'development'
};

const persistConfig = {
  name: 'my-storage-persist-name',
  storage: createJSONStorage(() => MMKVStorage),

  // or if you want, you can use AsyncStorage instead of MMKV
  // storage: createJSONStorage(() => AsyncStorage),

  // ... other persist configs here ...
}

const useMyAppStore = create<Store>()(
  devtools(
    persist((set, get) => ({
      // ... Store code here ...
    }), persistConfig),
    devtoolsConfig
  )
);

export default useMyAppStore;

Just a tip: If you're using React Native, it's necessary to adopt JSI Archtecture to use MMKV storage.

I hope this helps. Let me know if it worked

Toxicology answered 20/3, 2023 at 15:31 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.