创建小部件列表时出错
如果我第一次点击小部件列表我能够创建小部件(小部件1)。
如果我创建另一个小部件,我会收到错误(状态突变)。
如果我创建另一个小部件,我可以创建没有错误的小部件(小部件3)
错误:在路径``中的调度之间检测到状态突变。这可能会导致不正确的行为。
码
addWidget = (widgetType) => {
let newWidget = {};
switch (widgetType) {
case 'venn':
newWidget = {
widgetName: `widget ${this.state.widgetCount}`,
widgetType: 'venn',
leftTarget: '',
rightTarget: '',
leftTargetValue: 0,
rightTargetValue: 0,
position: { row: 0, col: 0 },
};
break;
default:
newWidget = {
widgetName: `Default ${this.state.widgetCount}`,
widgetType: 'venn',
leftTarget: '',
rightTarget: '',
};
break;
}
this.setState(prevState => ({
widgetsList: [...this.state.widgetsList, newWidget],
isHidden: !prevState.isHidden,
widgetCount: this.state.widgetCount + 1,
}), () => this.props.storyboardActions.addWidget(newWidget, this.props.selectedBoard.boardId));
};
减速
case types.ADD_NEW_WIDGET: {
const newBoardList = state.boardList.map((item) => {
if (item.boardId === action.selectedBoardId) {
return {
...item,
modifiedAt: Date.now(),
widgetList: [...(item.widgetList || []), { widgetId: uuid(), ...action.newWidget }],
};
}
return item;
});
return { ...state, boardList: [...newBoardList] };
}
动作
export const addWidget = (newWidget, selectedBoardId) => ({
type: types.ADD_NEW_WIDGET,
payload: {
widget: newWidget,
boardId: selectedBoardId,
},
});
答案 0 :(得分:1)
编辑:动作创建者中的错误
尝试使用action.payload传递所有数据。你现在有了你的属性名称的错误,并且你正在以错误的顺序调用params的动作创建者:
// Action Creator
export const addWidget = (newWidget, selectedBoardId) => ({ // <-- Param order
type: types.ADD_NEW_WIDGET,
payload: { // <-- Use payload object
boardId: selectedBoardId, // <-- These key names
widget: newWidget,
}
});
// Reducer
case types.ADD_NEW_WIDGET: {
const { boardId, widget } = action.payload; // <-- Get the data out
const newBoardList = state.boardList.map(item => {
if (item.boardId === boardId) {
const currentWidgetList = item.widgetList || [];
const newWidgetList = [
...currentWidgetList,
{
widgetId: uuid(),
...widget
}
];
return {
...item,
modifiedAt: Date.now(),
widgetList: newWidgetList
};
}
return item;
});
return { ...state, boardList: newBoardList };
}
我可以看到您的storyboardActions.addWidget
actionCreator吗?
我知道可能出现什么问题。 spread运算符是一个浅层克隆,因此不能保证不可变。 (查看cloneDeep选项。)
但是,我并不认为正在变异的是什么。我对您发布的代码最好的想法是widgetName
,因为它依赖于this.state.widgetCount
来获取唯一名称,但setState
方法是异步的,所以从技术上来说它有机会出错(我想。)
我稍微重构了你的代码。我的变化不大,所以我不指望这个解决问题。但是像这样将这些位分开会让你有机会在console.logs中投入,以便有希望找到发生突变的地方。
让我知道这是否会有所不同:
getNewWidget = type => {
switch (widgetType) {
case "venn":
return {
widgetName: `widget ${this.state.widgetCount}`,
widgetType: "venn",
leftTarget: "",
rightTarget: "",
leftTargetValue: 0,
rightTargetValue: 0,
position: { row: 0, col: 0 }
};
default:
return {
widgetName: `Default ${this.state.widgetCount}`,
widgetType: "venn",
leftTarget: "",
rightTarget: ""
};
}
};
addWidget = widgetType => {
const newWidget = this.getNewWidget(widgetType);
this.setState(
{
widgetsList: [...this.state.widgetsList, newWidget],
isHidden: !this.state.isHidden,
widgetCount: this.state.widgetCount + 1
},
() =>
this.props.storyboardActions.addWidget(
newWidget,
this.props.selectedBoard.boardId
)
);
};
减速
case types.ADD_NEW_WIDGET: {
const newBoardList = state.boardList.map(item => {
if (item.boardId === action.selectedBoardId) {
const currentWidgetList = item.widgetList || [];
const newWidgetList = [
...currentWidgetList,
{
widgetId: uuid(),
...action.newWidget
}
];
return {
...item,
modifiedAt: Date.now(),
widgetList: newWidgetList
};
}
return item;
});
return { ...state, boardList: newBoardList };
}
答案 1 :(得分:0)
一个导致我犯此错误的常见错误是,当我从道具克隆到状态时。
getFields(props) {
return ((props.resources.fields && [...props.resources.fields]) || []).map(
field => {
field.checked = false;
return field;
}
);
}
this.setState({ fields: getFields(props) });
在上面的示例中,fields
是一个对象数组。而且我没有进行深层复制,而是使用[...props.resources.fields]
进行了浅层复制。
进行深层复制可以解决此问题。因此,对于我来说,我做了如下的浅层复制:
getFields(props) {
return ((props.resources.fields && [...props.resources.fields]) || []).map(
item => {
const field = { ...item };
field.checked = false;
return field;
}
);
}