Angular 2 ngrx :在化简器中不可变地更新对象数组的正确方法是什么



在我的 Angular2 应用程序中,我使用 ngrx 来管理状态,因此当我从服务器接收数据时,我会将一个动作调度给化简器。

MyExampleReducer.ts :

export const Reviews: ActionReducer<any> = (state: any[] = [], action: Action) => {
switch (action.type) {
        case GET_REVIEWS:
            return action.payload;
        case ADD_REVIEW :
            return [...state, {review : action.payload, replays : []}];
        case UPDATE_REVIEW:
            return  '' // return what ? 
        case DELETE_REVIEW:
            return state.filter(item => {
                return item.id !== action.payload.id;
            });
        default:
            return state;
    }
};

问题是当我必须更新 Reviews 数组中的项目时,以 redux 方式执行的最佳方法是什么?

您可以使用

map 返回一个数组,该数组具有与更新的操作对应的元素:

export const Reviews: ActionReducer<any> = (state: any[] = [], action: Action) => {
  switch (action.type) {
    case ADD_REVIEW:
      return [...state, { review: action.payload, replays: [] }];
    case UPDATE_REVIEW:
      return state.map(item => item.id === action.payload.id ? { review: action.payload, replays: [] } : item);
    case DELETE_REVIEW:
      return state.filter(item => item.id !== action.payload.id);
    default:
      return state;
    }
}

此外,您可以通过使用评论缩减器来简化评论缩减器来执行ADD_REVIEWUPDATE_REVIEW操作 - 评论缩减器只关心管理评论列表,而不关心评论本身:

import { reviewReducer } from '...';
export const Reviews: ActionReducer<any> = (state: any[] = [], action: Action) => {
  switch (action.type) {
    case ADD_REVIEW:
      return [...state, reviewReducer(undefined, action)];
    case UPDATE_REVIEW:
      return state.map(item => item.id === action.payload.id ? reviewReducer(item, action) : item);
    case DELETE_REVIEW:
      return state.filter(item => item.id !== action.payload.id);
    default:
      return state;
    }
}

假设您的状态只是一个充满评论的数组,您可以执行以下操作:

export const Reviews: ActionReducer<any> = (state: any[] = [], action: Action) => {
switch (action.type) {
        case GET_REVIEWS:
            return action.payload;
        case ADD_REVIEW :
            return [...state, {review : action.payload, replays : []}];
        case UPDATE_REVIEW:
            // get an array of all ids and find the index of the required review
            let index = state.map(review => review.id)
                        .indexOf(action.payload.id);
            return [
              ...state.slice(0, index),
              Object.assign({}, state[index], action.payload),
              ...state.slice(index + 1)
            ]
        case DELETE_REVIEW:
            return state.filter(item => {
        return item.id !== action.payload.id;
        });
        default:
            return state;
}

首先,您需要找到应更新的评论索引。之后,您可以创建一个新数组,在其中替换索引位置的对象。

这种突变的一个很好的资源是这个视频。

最新更新