首页 > 解决方案 > 使用 Redux 和 Saga 将状态持久化到本地存储

问题描述

我正在关注Dan Abramov的教程。但是,我在步骤添加persistedStatecreateStore

我的代码是这样的:

const persistedState = loadState();

const store = createStore(
  reducers,
  composeEnhancers(applyMiddleware(sagaMiddleware))
)

store.subscribe(throttle(() => {
  saveState({
    authReducer: store.getState().authpage
  })
}, 1000));

我怎样才能persistedState通过createStore中间件redux-saga

我的减速机:

const reducer = combineReducers({
[authpageContext]: authReducer,
  [profilepageContext]: profileReducer,
  [reportpageContext]: reportReducer,
  [learningContext]: learningReducer,
  [globalContext]: globalReducer,
})

我的传奇:

export default function* rootSaga() {
  yield all([
    authPageSaga(),
    profilePageSaga(),
    learningSaga(),
    reportPageSaga()
  ])
}

更新

得到一些帮助后。我已连接到 sagas,现在我可以将数据保存到其中。但是这一步我很困惑。

loadState函数向我返回一个对象 localStorage auth,如下所示:

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1lbWJlcjJAZ21haWwuY29tIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJpYXQiOjE1MzEzOTE1NTMsImV4cCI6MTUzMTM5NTE1M30.75vj-YCeJtxuXjOqzisVRkFVMKe7fcpHLByWQ-x_frE",
    "user": {
        "id": 2,
        "email": "member2@gmail.com",
        "firstName": "Mr. Pierre",
        "lastName": "Schneider",
        "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/stalewine/128.jpg",
        "address": "4706 Kessler Turnpike Apt. 800 Rautown Borders",
        "phone": "021-292-7337",
        "division": "Front End Group 1",
        "password": "123456",
        "role": "member"
}

接下来我们如何加载该auth对象并保存initStateauthReducer

authReducer:

const initState = {
  token: '',
  user: {},
  error: false
}

function authReducer(state = initState, action) {
  switch (action.type) {
    case AUTH_LOGIN_SUCCEEDED:
      return {
        ...state,
        user: action.userResponse
      }
    case AUTH_LOGOUT_SUCCEEDED:
      return {
        ...state,
        user: action.userResponse
      }
    case AUTH_LOGIN_FAILED:
    case AUTH_LOGOUT_FAILED:
      return {
        ...state,
        error: true,
        user: {}
      }
    default:
      return state
  }
}

我试过这样做:

const persistedState = loadState();

const store = createStore(
  reducers,
  persistedState,
  composeEnhancers(applyMiddleware(sagaMiddleware))
)

store.subscribe(throttle(() => {
  saveState({
    access_token: store.getState().authpage.token,
    user: store.getState().authpage.user,
  })
}, 1000));

但在authReducer. 它没有返回我预期的状态。

它向我显示了一个错误:

Unexpected keys "access_token", "user" found in previous state received by the reducer. Expected to find one of the known reducer keys instead: "authpage", "profilepage", "flashmessage", "reportpage", "learning", "global". Unexpected keys will be ignored.

我在这里做错了什么?

标签: javascriptreactjsreduxredux-saga

解决方案


只要loadState是同步的并且键名相同,您只需将persistedState其作为第二个参数传递

const store = createStore(
  reducers,
  persistedState,
  composeEnhancers(applyMiddleware(sagaMiddleware))
)

文档

  1. [preloadedState](any):初始状态。您可以选择指定它以在通用应用程序中混合来自服务器的状态,或恢复以前序列化的用户会话。如果您使用 combineReducers 生成 reducer,则这必须是一个普通对象,其形状与传递给它的键的形状相同。否则,您可以自由传递您的减速器可以理解的任何内容。

UPD 由于持久值的结构与商店的结构不同,因此您需要persistedState在将值传递给之前准备好值createStore

const store = createStore(
  reducers,
  {
    [authpageContext]: {
      token: persistedState.access_token,
      user: persistedState.user
    }
  },
  composeEnhancers(applyMiddleware(sagaMiddleware))
)

或者在持久化状态时简单地使用相同的名称以避免额外的转换。

store.subscribe(throttle(() => {
  saveState({
    [authpageContext]: store.getState()[authpageContext]
  })
}, 1000));

推荐阅读