我已经完成了React拖放功能到我的项目中,因此我可以在React表的列表中对行进行重新排序。问题是我有一个名为“序列”的列,女巫向我显示了元素的顺序,我无法更新其值。
示例:
之前(行可拖动):
Sequence | Name
1 Jack
2 Angel
之后(我需要更新Sequence的值,其中在放置特定的可拖动行之后更改其位置,在这种情况下,我将Jack拖到第一个位置,并将其拖到第二个位置):
Sequence | Name
1 Angel
2 Jack
React / Redux允许我更改此元素数组的索引顺序,而不会收到“在两次派发之间检测到状态突变”错误消息,但不允许我用新的更新Sequence值订单值。
这是我到目前为止尝试过的:
// within the parent class component
// item is an array of objects from child
UpdateSequence(startIndex, endIndex, item) {
// the state.Data is already an array of object
const result = this.state.Data;
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
// this is working without the mutation state error
this.setState({ Data: result })
let positionDiff = 0;
let direction = null;
let newIndex = 0;
positionDiff = endIndex - startIndex;
if (startIndex > endIndex) {
direction = "up";
}
else if (startIndex < endIndex) {
direction = "down";
}
if (positionDiff !== 0) {
for (var x = 0; x <= Math.abs(positionDiff); x++) {
if (x === 0) {
newIndex = startIndex + positionDiff - x;
this.setState(prevState => ({
Data: {
...prevState.Data,
[prevState.Data[newIndex].Sequence]: Data[newIndex].Sequence + positionDiff
},
}));
}
else {
if (direction === "down") {
newIndex = startIndex + positionDiff - x;
this.setState(prevState => ({
Data: {
...prevState.Data,
[prevState.Data[newIndex].Sequence]: Data[newIndex].Sequence - 1
},
}));
}
else if (direction === "up") {
Data= startIndex + positionDiff + x;
this.setState(prevState => ({
Data: {
...prevState.Data,
[prevState.Data[newIndex].Sequence]: Data[newIndex].Sequence + 1
},
}));
}
}
}
// so when i call save action i am stepping into the 'A state mutation was detected between dispatches' error message.
this.props.actions.saveSequence(this.state.Data)
.then(() => {
this.props.actions.loadData();
})
.catch(error => {
toastr['error'](error, 'error....');
})
}
每当我尝试更新数组元素“序列”时,调用操作“ saveSequence”,即得到“在两次调度之间检测到状态突变”错误消息。
任何帮助都将非常有用!谢谢!
注意:用于重新排序序列的逻辑是可以的。
答案 0 :(得分:0)
虽然我不太了解redux,但我注意到您正在直接修改state
,这似乎是罪魁祸首。
const result = this.state.Data;
const [removed] = result.splice(startIndex, 1);
splice
是一种破坏性方法,会修改其输入,并且其输入是对this.state
中某些内容的引用。
演示:
> state = {Data: [1,2,3]}
{ Data: [ 1, 2, 3 ] }
> result = state.Data.splice(0,1)
[ 1 ]
> state
{ Data: [ 2, 3 ] }
请注意,state
已被修改。这可能是Redux所检测到的,也是一般的反应禁忌。
为避免修改状态,最简单的方法是克隆您要修改的数据
const result = this.state.Data.slice()
请注意,这会复制 shallow ,因此,如果Data
具有非原始值,则还必须注意对这些值进行破坏性编辑。 (如果要了解更多信息,请查找深层副本与浅层副本。)但是,由于您只是重新排序商品,因此我相信您是安全的。
答案 1 :(得分:0)
好吧,我发现更改了这部分代码:
//code....
const result = item;
const [removed] = result.splice(startIndex, 1);
// i created a new empty copy of the const 'removed', called 'copy' and update the Sequence property of the array like this below. (this code with the sequence number is just a sample of what i came up to fix it )
let copy;
copy = {
...removed,
Sequence: 1000,
};
result.splice(endIndex, 0, copy);
在我没有设置状态之后,我评论了这一行:
// this.setState({ Data: result })
//...code
,最后将结果作为参数而不是状态放入保存操作。
this.props.actions.saveSequence(result)
Works,现在我可以完全拖放功能,将新订单序列保存到数据库中,而不再出现“在两次派遣之间检测到状态突变”错误消息!