使用Redux和Saga将状态持久化到本地存储

时间:2018-07-16 11:24:16

标签: javascript reactjs redux redux-saga

我正在关注Dan Abramov的the tutorial。但是,我在将persistedState添加到createStore

时感到困惑

我的代码如下:

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对象并保存到initState中的authReducer

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.

我在这里错了什么?

1 个答案:

答案 0 :(得分:1)

假设loadState是同步的,并且键名与您只需传递persistedState作为第二个参数一样

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

Docs

  
      
  1. [preloadedState](任意):初始状态。您可以选择指定   它可以在通用应用中从服务器中混合状态,或者   恢复先前序列化的用户会话。如果生产减速器   使用CombineReducers,它必须是形状相同的普通对象   作为密钥传递给它。否则,您可以自由传递任何东西   减速器可以理解的。
  2.   

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));