UNPKG

@stainless-code/persist

Version:

Hydration-aware persistence for any reactive store — zero-dep persistSource core; codecs, backends, cross-tab transport, source + framework hydration adapters ship as opt-in recipes

66 lines (65 loc) • 2.39 kB
import { l as persistSource } from "../persist-core-B5VikEft.mjs"; //#region src/adapters/sources/redux.ts /** Private set/hydrate action — owned by this module; not for app dispatch. */ const PERSIST_SET = "@stainless-code/persist/SET"; /** * Wrap the root reducer so hydrate/`setState` can replace state. Do not wrap * slices inside `combineReducers` — the payload is the full root. Without this, * RTK slices ignore the private action (silent no-op). Named to avoid clashing * with redux-persist's `persistReducer`. * * @example * ```ts * import { createStore } from "redux"; * import { persistableReducer } from "@stainless-code/persist/sources/redux"; * const store = createStore(persistableReducer(rootReducer)); * ``` */ function persistableReducer(baseReducer) { return (state, action) => { if (action.type === PERSIST_SET) return action.payload; return baseReducer(state, action); }; } /** * Persist a Redux store (classic `createStore` or RTK `configureStore`). * Redux has no `setState` — hydrate/writes dispatch a private action handled * by {@link persistableReducer} on the root. Do not use `replaceReducer` for * hydrate. * * If you also import redux-persist's `persistStore`, alias this one: * `import { persistStore as persistWithStainless } from "@stainless-code/persist/sources/redux"`. * * @example * ```ts * import { createStore } from "redux"; * import { createJSONStorage } from "@stainless-code/persist"; * import { * persistStore, * persistableReducer, * } from "@stainless-code/persist/sources/redux"; * const store = createStore(persistableReducer(rootReducer)); * const persist = persistStore(store, { * name: "root", * storage: createJSONStorage(() => localStorage), * }); * ``` */ function persistStore(store, options) { return persistSource({ getState: () => store.getState(), setState: (updater) => { const prev = store.getState(); const payload = updater(prev); const action = { type: PERSIST_SET, payload }; store.dispatch(action); if (process.env.NODE_ENV !== "production" && store.getState() === prev) console.warn("[@stainless-code/persist/sources/redux] setState/hydrate did not apply. Wrap the root reducer with persistableReducer (not each slice)."); }, subscribe: (listener) => ({ unsubscribe: store.subscribe(listener) }) }, options); } //#endregion export { persistStore, persistableReducer };