Persisting & rehydrating data
Previous versions of zfy used to rely on a custom persistence solution. Fortunately, zustand added built-in support for this feature in v3.1.4. Therefore: zfy simply employs zustand's persist middleware and tries to offer an easier API to use.
Persistence
Data is persisted on a store to store basis. In order to make a store persist its data
, you need to provide the persist
option to createStore()
3rd argument and specify which storage solution you'd like to use:
import AsyncStorage from '@react-native-async-storage/async-storage'
import { createStore } from '@colorfy-software/zfy'
import type { StoresDataType } from '../types'
export const initialState: StoresDataType['user'] = {
id: '',
likes: 0,
}
export default createStore<StoresDataType['user']>('user', initialState, {
persist: { getStorage: () => AsyncStorage },
})
This means that you can have stores using different storage solutions depending on your use case (LocalStorage, Cookies, IndexedDB, etc).
You need to make sure that your storage solution provides agetItem()
, asetItem()
and aremoveItem()
(only needed for zustand v4).
If it does not, of course, you can always provide it yourself:
import { MMKV } from 'react-native-mmkv'
import { createStore } from '@colorfy-software/zfy'
import type { StoresDataType } from '../types'
export const initialState: StoresDataType['user'] = {
id: '',
likes: 0,
}
export const storage = new MMKV({ id: 'user' })
export default createStore<StoresDataType['user']>('user', initialState, {
persist: {
getStorage: () => ({
getItem: (name) => storage.getString(name) ?? null,
setItem: (name, value) => storage.set(name, value),
removeItem: (name) => storage.delete(name),
}),
},
})
From there you're all set. Just use getState().update()
to update your store as covered in the Creating & using a store guide and your data
will be persisted.
Rehydration
Similarly to the persistence solution, zfy directly uses zustand's rehydration under the hood and simply exposes it via a different (hopefully simpler) API.
Usually, when it comes to rehydration, you might want to hide all (or part) of your app while the necessary stores are rehydrating. zfy provides 2 solutions out of the box to do so: a component - <PersistGate/>
- and a React Hook, useRehydrate()
.
<PersistGate />
<PersistGate />
This component expects an array of stores
and will take care of displaying its children
only when all the stores will have been rehydrated. You can as well provide a loader
if needed:
import { SafeAreaView, Text } from 'react-native'
import { PersistGate } from '@colorfy-software/zfy'
import appStore from './stores/app-store'
import userStore from './stores/user-store'
const Loader = () => (
<SafeAreaView>
<Text>ā³ Loading...</Text>
</SafeAreaView>
)
export default function App() {
return (
<PersistGate stores={[appStore, userStore]} loader={<Loader />}>
<MyApp />
</PersistGate>
)
}
useRehydrate()
useRehydrate()
If <PersistGate />
doesn't fit your need, you can have finer control over what happens via useRehydrate()
:
import { useEffect } from 'react'
import { SafeAreaView, Text } from 'react-native'
import { useRehydrate } from '@colorfy-software/zfy'
import appStore from './stores/app-store'
import userStore from './stores/user-store'
const Loader = () => (
<SafeAreaView>
<Text>Loading...</Text>
</SafeAreaView>
)
export default function App() {
const isRehydrated = useRehydrate([appStore, userStore])
useEffect(() => {
if (isRehydrated) {
// š Trigger side effect upon rehydration?
}
}, [isRehydrated])
return isRehydrated ? <Loader /> : <MyApp />
}
Last updated
Was this helpful?