我有一个公司和公司内部的对象,有一系列的团队。
company: {
teams: [
{
name: 'test team',
description: 'dddd',
team_manager: null,
company: '592577d5b591966c8e535865',
permalink: 'test-team',
createdAt: '2017-05-30T07:38:58.983Z',
updatedAt: '2017-05-30T07:38:58.983Z',
id: '592d219277923054118e7299'
}
],
name: 'test company2',
createdAt: '2017-05-24T12:08:53.418Z',
updatedAt: '2017-05-24T12:08:53.419Z',
id: '592577d5b591966c8e535865'
}
}
添加团队后,我正在使用此缩减器将团队推送到阵列。
case types.ADD_TEAM_SUCCESS :
return Object.assign({}, state, state.teams.push(action.newTeam));
这很好,但是,在控制台中我收到一条警告:
'错误:在调度中检测到状态突变,路径为:company.teams.0
'
关闭对象并将新团队推送到阵列的正确方法是什么?
答案 0 :(得分:3)
如果您使用的是es2015,我可以执行以下操作:
return Object.assign({}, state, { teams: [...state.teams, action.newTeam] });
您正在将对象直接推送到state.teams
。您应该先复制并使用它。如果您不能使用spread运算符,则可以将state.teams切片为一个新变量,然后将其推送到该变量。
答案 1 :(得分:0)
问题在于Object.assign()
没有对您的对象[1]进行深度克隆(请参阅"深度克隆警告")。
如果您的堆栈中没有任何实用程序库(如lodash),您可以使用JSON编码和解码来完成工作:
case types.ADD_TEAM_SUCCESS:
let stateCopy = JSON.parse(JSON.stringify(state));
state.teams.push(action.newTeam);
return state;
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
答案 2 :(得分:0)
如前所述,Object.assign()不会对您的对象进行深层克隆。
我的建议是规范您的商店并分成两个商店公司和团队。
使用combineReducers并将其连接到一个商店,您将简化Reducer并使代码更具可读性。你也可以玩性能。
我的意思是......如果你的组件只是与公司合作而你将改变团队,你将避免轻易重新渲染。
检查Dan Abramov炉排视频教程 Redux: Normalizing the State Shape
我会以某种方式这样做(抱歉打字稿中的代码)
export interface ICompanyItem {
name: string;
id: string;
createdAt: Date;
updatedAt: Date;
}
export interface ITeamItem {
id: string;
companyId: string
name: string;
description: string;
team_manager: string;
createdAt: Date;
updatedAt: Date;
}
export interface ICompaniesState {
items: { [id: string]: ICompanyItem };
}
export interface ITeamsState {
items: { [id: string]: ITeamItem };
}
export const teamsReducer: Reducer<ITeamsState> = (state: ITeamsState, action: Action) => {
if (isActionType(action, AddNewTeamItem)) {
let itemsClone: { [id: string]: ITeamItem } = { ...state.items, [action.id]: action.team };
return {
...state,
items: itemsClone
};
}
return state || unloadedState;
};