首页 > 解决方案 > 从存储中存储和检索状态

问题描述

我正在尝试userToken在 Redux 存储中保存并检索它。在我的index.js我包装我App的 with Provider,它store作为道具:

import { createStore } from "redux";
import { Provider } from "react-redux";
import rootReducer from "./reducers/rootReducer";

const store = createStore(rootReducer);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

我的rootReducer样子是这样的:

//Helper functions
import { validateLoginAttempt } from "../helpers/validateLoginAttempt";

const rootReducer = (state, action) => {
  switch (action.type) {
    case "login":
      const isLoggedIn = validateLoginAttempt(action.payload);
    default:
      console.log("default");
      break;
  }
};

export default rootReducer;

我定义了一个辅助函数validateLoginAttempt

export const validateLoginAttempt = payload => {
  if (typeof payload.data.token !== "undefined") {
    //Saves in localstorage correctly.
    localStorage.setItem("userToken", payload.data.token);

    return true;
  }

  return false;
};

在我的一个功能组件中,我有一个fetch()程序,在对 API 的请求结束时,它是dispatch()我在我的定义中定义的操作rootReducer

const dispatch = useDispatch();
<...>
.then(data => {
  dispatch({ type: "login", payload: { data } });
  history.push("/");
})

useCase至少从我的理解来看,这个流程按预期工作,值被存储在localStorage其中(我假设它不是 Redux store?)。在我的另一个组件中,我试图userToken像这样检索:

const userToken = useSelector(state => state.userToken);

这给了我一个error

Error: An error occured while selecting the store state: Cannot read property 'userToken' of undefined.

如果我在我的组件中尝试getStore如下操作,我会得到:Appstore undefined

const store = useStore();
console.log("store", store.getState());

有人可以让我走上正轨,无法弄清楚。

标签: reactjsreduxreact-reduxreact-hooks

解决方案


有多个问题,但最大的一个与减速器的基础有关

reducer 是一个纯函数,它接受前一个状态和一个动作,并返回下一个状态

您不会从减速器(隐式return undefined)返回任何内容,从而导致 TypeError Cannot read property 'userToken' of undefined.

const initialState = {};
const rootReducer = (state = initialState, action) => {
  switch (action.type) {
    case "login": {
      return {...state, userToken: action.payload.data.token};
    }
    default:
      return state;
  }
};

而“纯函数”意味着没有副作用,所以localStorage.setItem内部validateLoginAttempt在 reducer 中没有位置,应该放在 action creator 内部:

const dispatch = useDispatch();
...
.then(data => {
  const isLoggedIn = validateLoginAttempt(data);
  if (isLoggedIn) {
    dispatch({ type: "login", payload: { data } });
    history.push("/");
  } else {
    console.error("not logged in")
  }
})

推荐阅读