use immer as middleware

This commit is contained in:
austinried
2022-03-24 12:00:06 +09:00
parent 1a920e195f
commit 8412c33923
6 changed files with 291 additions and 309 deletions

View File

@@ -1,13 +1,15 @@
import { createSettingsSlice, SettingsSlice } from '@app/state/settings'
import AsyncStorage from '@react-native-async-storage/async-storage'
import equal from 'fast-deep-equal/es6/react'
import create, { GetState, Mutate, SetState, StateSelector, StoreApi } from 'zustand'
import create, { GetState, Mutate, SetState, State, StateCreator, StateSelector, StoreApi } from 'zustand'
import { persist, subscribeWithSelector } from 'zustand/middleware'
import { CacheSlice, createCacheSlice } from './cache'
import { createLibrarySlice, LibrarySlice } from './library'
import migrations from './migrations'
import { createTrackPlayerSlice, TrackPlayerSlice } from './trackplayer'
import { createTrackPlayerMapSlice, TrackPlayerMapSlice } from './trackplayermap'
import produce, { Draft } from 'immer'
import { WritableDraft } from 'immer/dist/internal'
const DB_VERSION = migrations.length
@@ -20,6 +22,37 @@ export type Store = SettingsSlice &
setHydrated: (hydrated: boolean) => void
}
// taken from zustand test examples:
// https://github.com/pmndrs/zustand/blob/v3.7.1/tests/middlewareTypes.test.tsx#L20
const immer =
<
T extends State,
CustomSetState extends SetState<T>,
CustomGetState extends GetState<T>,
CustomStoreApi extends StoreApi<T>,
>(
config: StateCreator<
T,
(partial: ((draft: Draft<T>) => void) | T, replace?: boolean) => void,
CustomGetState,
CustomStoreApi
>,
): StateCreator<T, CustomSetState, CustomGetState, CustomStoreApi> =>
(set, get, api) =>
config(
(partial, replace) => {
const nextState = typeof partial === 'function' ? produce(partial as (state: Draft<T>) => T) : (partial as T)
return set(nextState, replace)
},
get,
api,
)
export type SetStore = (partial: Store | ((draft: WritableDraft<Store>) => void), replace?: boolean | undefined) => void
export type GetStore = GetState<Store>
// types taken from zustand test examples:
// https://github.com/pmndrs/zustand/blob/v3.7.1/tests/middlewareTypes.test.tsx#L584
export const useStore = create<
Store,
SetState<Store>,
@@ -28,7 +61,7 @@ export const useStore = create<
>(
subscribeWithSelector(
persist(
(set, get) => ({
immer((set, get) => ({
...createSettingsSlice(set, get),
...createLibrarySlice(set, get),
...createTrackPlayerSlice(set, get),
@@ -36,13 +69,15 @@ export const useStore = create<
...createCacheSlice(set, get),
hydrated: false,
setHydrated: hydrated => set({ hydrated }),
}),
setHydrated: hydrated =>
set(state => {
state.hydrated = hydrated
}),
})),
{
name: '@appStore',
version: DB_VERSION,
getStorage: () => AsyncStorage,
// whitelist: ['settings', 'cacheFiles'],
partialize: state => ({ settings: state.settings, cacheFiles: state.cacheFiles }),
onRehydrateStorage: _preState => {
return async (postState, _error) => {