【问题标题】:Redux store not updatingRedux 商店不更新
【发布时间】:2019-07-21 09:00:10
【问题描述】:

我有一个关注rootReducer,它应该在商店内添加userToken:

const initialState = {
  userToken: ""
};

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

export default rootReducer;

在我的LoginForm 组件中,我将mapDispatchToProps 定义如下:

const mapDispatchToProps = dispatch => {
  return {
    saveUserToken: token => {
      dispatch({ type: "login", payload: token });
    }
  };
};

并使用connect() 导出我的组件(我通过null,因为这里没有mapStateToProps):

export default connect(
  null,
  mapDispatchToProps
)(LoginForm);

我在我的组件中调用它:

.then(data => {
  props.saveUserToken(data);
})

我确信我的rootReducer 的login 案例会被调用,因为我可以在其中console.log() 并将userToken 保存在localStorage 中。

现在在我的另一个组件中,它侦听另一个路由,我像这样注册mapStateToProps:

const mapStateToProps = state => {
  return {
    userToken: state.userToken
  };
};

<...>

export default connect(mapStateToProps)(ServerList);

在ServerList里面,我定义如下:

const ServerList = ({ userToken }) => {}

在useEffect钩子里面,我尝试console.log(userToken);。我得到的是空字符串。有什么问题?

const ServerList = ({ userToken }) => {

  useEffect(() => {
    console.log(userToken);      
    //returns ''  
  });
  <...>

编辑: 为了测试,我在LoginForm 中实现了mapStateToProps 和console.log'ed 在useEffect() 中:

useEffect(() => {
  console.log(props);
});

在提交表单时,userToken 值正确保存在 props 中,但如果我重新加载页面,userToken 会再次设置为空字符串。

【问题讨论】:

  • 这些组件是否连接到同一个商店实例?如果您将 mapStateToProps 添加到您的 LoginForm 中,userToken 的值是否会通过?
  • @dezfowler,我刚刚在我的登录表单中实现了mapStateToProps,并在useEffect() 中实现了console.log。在表单提交时,userToken 被定义并且值被正确地保存在props 中。但是如果我重新加载,或者再次访问/login 页面,userToken 是空的。
  • 您在缩减时使用action.payload.token,但正在调度dispatch({ type: "login", payload: token });。所以当调用saveUserToken(token)token 时应该是token: { token: /* token is here */ } 形式的对象。对吗?
  • @Kelb56 顺便说一句,你的 reducer 应该是一个纯函数,所以不应该引起像调用 localStorage.setItem() 这样的副作用。那个电话应该是middleware。

标签: reactjs react-redux react-hooks


【解决方案1】:

当您重新加载页面时,您在 redux 存储中的数据将被设置回其初始值。如果想保留重载页面的数据,可以使用redux-persist。

【讨论】:

  • 这是否意味着,如果我的 react-router-dom 有几条路线,我无法从不同路线上的商店获取状态?
  • 当您使用react-router-dom 更改路线时,不会重新加载页面。所以你在 redux 存储中的数据不会丢失。
  • 我很难在 .then() 函数中使用 history.push 实际重定向用户。除非我重新加载页面,否则它会更改 url 并且不会呈现我的组件在不同的路径上侦听。我尝试使用withRouter HOC,但没有帮助,也许你以前见过这个?
  • 你的 react-router 版本是什么?您是否尝试使用 withRouter?
  • 是的,我试过withRouter。 react-router 版本是 5.0.1,react-router-dom 版本也是 5.0.1。
【解决方案2】:

这样试试

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

export default rootReducer;

使用Object.assign

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-06
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 2018-06-18
    • 2020-06-10
    相关资源
    最近更新 更多