Hemendra  Khatik
Hemendra Khatik

Reputation: 481

Unable to use zustand persist middleware

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;


Upvotes: 9

Views: 14089

Answers (2)

NandoMB
NandoMB

Reputation: 431

The use of getStorage, inside persist middleware, is now 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)



Here is a complete example of usage with 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, createJSONStorage } 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

Upvotes: 13

Gift Brightson
Gift Brightson

Reputation: 163

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;

Upvotes: 4

Related Questions