我想将状态树的某些部分保留到 localStorage。什么地方适合这样做?减速器还是动作?
在 Redux 应用程序中写入 localStorage 的位置?
IT技术
javascript
redux
local-storage
state
2021-02-04 11:32:15
6个回答
Reducer 永远不是一个合适的地方,因为 reducer 应该是纯粹的并且没有副作用。
我建议只在订阅者中进行:
store.subscribe(() => {
// persist your state
})
在创建商店之前,阅读那些持久化的部分:
const persistedState = // ...
const store = createStore(reducer, persistedState)
如果您使用,combineReducers()
您会注意到尚未收到状态的减速器将使用其默认state
参数值正常“启动” 。这可能非常方便。
建议您对订阅者进行去抖,以免写入 localStorage 太快,否则会出现性能问题。
最后,您可以创建一个封装它的中间件作为替代方案,但我将从订阅者开始,因为它是一个更简单的解决方案并且可以很好地完成工作。
要填写 Dan Abramov 的答案的空白,您可以store.subscribe()
像这样使用:
store.subscribe(()=>{
localStorage.setItem('reduxState', JSON.stringify(store.getState()))
})
在创建商店之前,检查localStorage
并解析您的密钥下的任何 JSON,如下所示:
const persistedState = localStorage.getItem('reduxState')
? JSON.parse(localStorage.getItem('reduxState'))
: {}
然后将此persistedState
常量传递给您的createStore
方法,如下所示:
const store = createStore(
reducer,
persistedState,
/* any middleware... */
)
如果有人对上述解决方案有任何问题,您可以自己写。让我告诉你我做了什么。忽略saga middleware
事情只关注两件事localStorageMiddleware
和reHydrateStore
方法。在localStorageMiddleware
拉所有redux state
,并把它放在local storage
和rehydrateStore
把所有的applicationState
本地存储(如果存在),并将其放在redux store
import {createStore, applyMiddleware} from 'redux'
import createSagaMiddleware from 'redux-saga';
import decoristReducers from '../reducers/decorist_reducer'
import sagas from '../sagas/sagas';
const sagaMiddleware = createSagaMiddleware();
/**
* Add all the state in local storage
* @param getState
* @returns {function(*): function(*=)}
*/
const localStorageMiddleware = ({getState}) => { // <--- FOCUS HERE
return (next) => (action) => {
const result = next(action);
localStorage.setItem('applicationState', JSON.stringify(
getState()
));
return result;
};
};
const reHydrateStore = () => { // <-- FOCUS HERE
if (localStorage.getItem('applicationState') !== null) {
return JSON.parse(localStorage.getItem('applicationState')) // re-hydrate the store
}
}
const store = createStore(
decoristReducers,
reHydrateStore(),// <-- FOCUS HERE
applyMiddleware(
sagaMiddleware,
localStorageMiddleware,// <-- FOCUS HERE
)
)
sagaMiddleware.run(sagas);
export default store;
我无法回答@Gardezi,但基于他的代码的选项可能是:
const rootReducer = combineReducers({
users: authReducer,
});
const localStorageMiddleware = ({ getState }) => {
return next => action => {
const result = next(action);
if ([ ACTIONS.LOGIN ].includes(result.type)) {
localStorage.setItem(appConstants.APP_STATE, JSON.stringify(getState()))
}
return result;
};
};
const reHydrateStore = () => {
const data = localStorage.getItem(appConstants.APP_STATE);
if (data) {
return JSON.parse(data);
}
return undefined;
};
return createStore(
rootReducer,
reHydrateStore(),
applyMiddleware(
thunk,
localStorageMiddleware
)
);
不同之处在于我们只是保存一些动作,您可以使用 debounce 函数仅保存您状态的最后一次交互