【问题标题】:How to correctly change my state in my reducer如何正确更改我的减速器中的状态
【发布时间】:2018-02-09 23:26:38
【问题描述】:

所以我有一个从 API 获取的操作。

我从我的 API 中获取用户,它返回 JSON 并返回用户的操作和 json 值以及进度值。

  fetchUser: (userId) => {
    return dispatch => {
      dispatch({ type: Constants.USER_FETCHING });
      let url = 'http://localhost:4001/api/v1/users/'+ userId;
      axios.get(url)
        .then(function(data) {
          console.log('data returned is ' + JSON.stringify(data));
          dispatch({
            type: Constants.GET_USER,
            user: data.user,
            progress: data.progress,
          });
        });
    };
  },

现在在我的减速器中,我必须返回状态而不改变它:

import Constants from '../constants';

const initialState = {
  users: [],
  user: null,
  progress: null,
  fetching: false,
};

const users = (state = initialState, action) => {
    case Constants.USER_FETCHING:
      return {...state, fetching: true};
  switch (action.type) {
    case Constants.GET_USER:
      return ?????;
    default:
      return state;
  }
};

export default users;

我应该如何返回状态?

我看到了使用 Object.assign 的示例,但不确定如何为我的案例构建它:

return Object.assign({}, state, ????);

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    您可以像在 USER_FETCHING 中一样使用扩展运算符 ...

    case Constants.GET_USER:
        return {
            ...state,
            user: action.user,
            progress: action.progress
        };
    

    这会创建一个新对象,方法是首先设置与 state 上当前相同的属性,然后用来自 action 的新值覆盖 userprogress 属性。

    【讨论】:

    • 您可能还想将fetching 设置为false
    【解决方案2】:

    卡巴曼和托尼的答案都是正确的。此外,如果您使用的是babel,则默认情况下Object spread 编译为Object.assign,您可以在documentation 中阅读。

    要添加到这些答案,如果要更新 users 数组,可以使用扩展变换 (documentation):

    case Constants.GET_USER:
    return {
        ...state,
        user: action.user,
        progress: action.progress,
        users: [ ...state.users, action.user ]
    };
    

    这将为用户创建一个新数组,concat 使用现有数组,然后使用新的user

    但是,如果action 中的user 已经在现有数组中,它将被复制。您可以实施验证来避免这种情况,或者直接使用来自lodashunion(如果userStringNumber):

    ....
        users: union(state.users, [action.user])
    ...
    

    【讨论】:

      【解决方案3】:

      如果你要使用 Object.assign,那么它将是:

      return Object.assign({}, state, {user: action.user, progress: action.progress});
      

      它是如何工作的: Object.assign 得到 3 个对象:

      • {} - 空
      • 状态
      • {用户:action.user,进度:action.progress}

      并将它们一一合并为1个对象。

      将空对象 ( {} ) 作为第一个参数很重要,因为在这种情况下,来自 state 的 props/values 将被合并到空对象中,并且您将获得一个新副本。 如果您删除空对象或将 state 作为第一个参数 - 在这种情况下,所有内容都将合并到 state 并且您将有一个突变而不是复制。

      【讨论】:

      • 另一个例子是在变异状态之上使用 ...state 还是和你的一样?
      • 您可以根据需要使用 ...state 版本。我只是按照问题中的要求提供了 Object.assign 版本。
      猜你喜欢
      • 1970-01-01
      • 2018-08-08
      • 1970-01-01
      • 2017-11-10
      • 2021-10-13
      • 1970-01-01
      • 1970-01-01
      • 2018-09-10
      • 2021-07-18
      相关资源
      最近更新 更多