如何在我的减速机中正确改变我的状态

时间:2018-02-09 23:26:39

标签: reactjs redux

所以我有一个从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,
          });
        });
    };
  },

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

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

3 个答案:

答案 0 :(得分:2)

您可以像在...中一样使用点差运算符USER_FETCHING

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

这会创建一个新对象,首先设置与state上当前相同的属性,然后使用{{1}中的新值覆盖userprogress属性}}

答案 1 :(得分:1)

如果您打算使用Object.assign,那么它将是:

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

工作原理: Object.assign获取3个对象:

  • {} - 空
  • 状态
  • {user:action.user,progress:action.progress}

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

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

答案 2 :(得分:1)

Karbaman和Tony的答案都是正确的。此外,如果您正在使用Object.assign,则默认情况下,对象范围会编译为babel,您可以在documentation中阅读。

要添加这些答案,如果您要更新users数组,可以使用点差转换(documentation):

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

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

但是,如果user中的action已经在现有数组中,那么它将会重复。您可以实施验证以避免这种情况,或直接从lodash使用union(如果userStringNumber):

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