You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.1 KiB

2 years ago
// @flow
import type {
Persistor,
PersistConfig,
PersistorOptions,
PersistorState,
MigrationManifest,
RehydrateAction,
RehydrateErrorType,
} from './types'
import { createStore } from 'redux'
import { FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE } from './constants'
type PendingRehydrate = [Object, RehydrateErrorType, PersistConfig]
type Persist = <R>(PersistConfig, MigrationManifest) => R => R
type CreatePersistor = Object => void
type BoostrappedCb = () => any
const initialState: PersistorState = {
registry: [],
bootstrapped: false,
}
const persistorReducer = (state = initialState, action) => {
switch (action.type) {
case REGISTER:
return { ...state, registry: [...state.registry, action.key] }
case REHYDRATE:
let firstIndex = state.registry.indexOf(action.key)
let registry = [...state.registry]
registry.splice(firstIndex, 1)
return { ...state, registry, bootstrapped: registry.length === 0 }
default:
return state
}
}
export default function persistStore(
store: Object,
options?: ?PersistorOptions,
cb?: BoostrappedCb
): Persistor {
// help catch incorrect usage of passing PersistConfig in as PersistorOptions
if (process.env.NODE_ENV !== 'production') {
let optionsToTest: Object = options || {}
let bannedKeys = [
'blacklist',
'whitelist',
'transforms',
'storage',
'keyPrefix',
'migrate',
]
bannedKeys.forEach(k => {
if (!!optionsToTest[k])
console.error(
`redux-persist: invalid option passed to persistStore: "${k}". You may be incorrectly passing persistConfig into persistStore, whereas it should be passed into persistReducer.`
)
})
}
let boostrappedCb = cb || false
let _pStore = createStore(
persistorReducer,
initialState,
options && options.enhancer ? options.enhancer : undefined
)
let register = (key: string) => {
_pStore.dispatch({
type: REGISTER,
key,
})
}
let rehydrate = (key: string, payload: Object, err: any) => {
let rehydrateAction = {
type: REHYDRATE,
payload,
err,
key,
}
// dispatch to `store` to rehydrate and `persistor` to track result
store.dispatch(rehydrateAction)
_pStore.dispatch(rehydrateAction)
if (boostrappedCb && persistor.getState().bootstrapped) {
boostrappedCb()
boostrappedCb = false
}
}
let persistor: Persistor = {
..._pStore,
purge: () => {
let results = []
store.dispatch({
type: PURGE,
result: purgeResult => {
results.push(purgeResult)
},
})
return Promise.all(results)
},
flush: () => {
let results = []
store.dispatch({
type: FLUSH,
result: flushResult => {
results.push(flushResult)
},
})
return Promise.all(results)
},
pause: () => {
store.dispatch({
type: PAUSE,
})
},
persist: () => {
store.dispatch({ type: PERSIST, register, rehydrate })
},
}
if (!(options && options.manualPersist)){
persistor.persist()
}
return persistor
}