Immutable.js mergeDeepWith 问题
Immutable.js mergeDeepWith issue
我很有趣 Immutable.js 并且在将对象与数组合并时遇到问题。
我的合并函数是:
function singleTrackReducer(state = Immutable.Map(singleTrack), action) {
switch (action.type){
case AudioFormActions.CHANGE:
return state.mergeDeepWith((prev, next) => next, action.entity);
default:
return state;
}
}
我要合并到的对象如下所示:
const singleTrack = {
songTitle: '',
mainArtists: [],
featuredArtists: [],
releaseDate: '',
primaryGenre: '',
isExplicit: false,
labelName:'',
upCode: '',
eanCode: '',
isrcCode:'',
copyRight: ''
};
我正在尝试更新 mainArtists 属性.. 例如,我可以将几位艺术家添加到我的艺术家数组并成功执行更新。但是,当我从数组中删除一个对象时,它似乎被以前的对象填充。
比如说艺术家 Array 是 [drake, rihanna, tyga]
如果我用动作实体 [drake, rihanna, tyga, john] 调用该函数,它会正常更新并且 mainArtists 属性 变为 [drake, rihanna, tyga, john]。
当我删除一个艺术家示例 tyga 并且数组是 [drake, rihanna, john]
主要艺术家 属性 变成 [drake, rihanna, john, john]
任何人都可以解释我如何解决这个问题
我认为这段代码可以帮助您理解问题:
var Immutable = require('immutable');
console.log(
Immutable.List(['a', 'b', 'c'])
.mergeDeep(['a', 'c'])
);
// output: List [ "a", "c", "c" ]
console.log(Immutable.List(['a', 'b', 'c'])
.mergeDeepWith((prev, next) => {
console.log(`Conflict between ${prev} and ${next}.`);
return next;
}, ['a', 'c'])
);
// output: Conflict between a and a.
// Conflict between b and c.
// List [ "a", "c", "c" ]
基本上,当合并列表时,项目似乎在每个索引处从一个复制到另一个,如果该索引处已经有一个值,则认为存在冲突:
- 对于索引 #0,第一个列表中有 "a",第二个列表中有 "a"。我们通过选择第二个值来解决冲突(尽管在本例中它们是相同的)。所以索引 #0 得到 "a".
- 然后我们转到索引 #1,发现第一个列表有 "b",第二个列表有 "c"。我们通过选择第二个值来解决冲突,因此索引 #1 得到 "c".
- 现在对于索引 #2,我们没有冲突,因为只有第一个列表有值。我们将 "c" 保留在索引 #2 中,因此最终列表为 "a"、"c"、"c".
您可以改用集合,但它基本上执行联合操作,因此不会删除任何内容:
console.log(
Immutable.Set(['a', 'b', 'c'])
.mergeDeep(['a', 'c'])
);
// output: Set { "a", "b", "c" }
我实际上并不认为您要合并此列表...我认为您只是想将新值复制到旧值上。如果是这样,也许您只是在寻找 merge
而不是 mergeDeep
:
var state = Immutable.Map({
songTitle: '',
mainArtists: [],
featuredArtists: [],
releaseDate: '',
primaryGenre: '',
isExplicit: false,
labelName:'',
upCode: '',
eanCode: '',
isrcCode:'',
copyRight: ''
});
function doMerge(state, newState) {
// no deep merge here, just copy whatever fields are present in newState
return state.merge(newState);
}
console.log(state.get('mainArtists'));
// output: []
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'tyga']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "tyga" ]
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'tyga', 'john']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "tyga", "john" ]
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'john']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "john" ]
我很有趣 Immutable.js 并且在将对象与数组合并时遇到问题。
我的合并函数是:
function singleTrackReducer(state = Immutable.Map(singleTrack), action) {
switch (action.type){
case AudioFormActions.CHANGE:
return state.mergeDeepWith((prev, next) => next, action.entity);
default:
return state;
}
}
我要合并到的对象如下所示:
const singleTrack = {
songTitle: '',
mainArtists: [],
featuredArtists: [],
releaseDate: '',
primaryGenre: '',
isExplicit: false,
labelName:'',
upCode: '',
eanCode: '',
isrcCode:'',
copyRight: ''
};
我正在尝试更新 mainArtists 属性.. 例如,我可以将几位艺术家添加到我的艺术家数组并成功执行更新。但是,当我从数组中删除一个对象时,它似乎被以前的对象填充。
比如说艺术家 Array 是 [drake, rihanna, tyga]
如果我用动作实体 [drake, rihanna, tyga, john] 调用该函数,它会正常更新并且 mainArtists 属性 变为 [drake, rihanna, tyga, john]。
当我删除一个艺术家示例 tyga 并且数组是 [drake, rihanna, john]
主要艺术家 属性 变成 [drake, rihanna, john, john]
任何人都可以解释我如何解决这个问题
我认为这段代码可以帮助您理解问题:
var Immutable = require('immutable');
console.log(
Immutable.List(['a', 'b', 'c'])
.mergeDeep(['a', 'c'])
);
// output: List [ "a", "c", "c" ]
console.log(Immutable.List(['a', 'b', 'c'])
.mergeDeepWith((prev, next) => {
console.log(`Conflict between ${prev} and ${next}.`);
return next;
}, ['a', 'c'])
);
// output: Conflict between a and a.
// Conflict between b and c.
// List [ "a", "c", "c" ]
基本上,当合并列表时,项目似乎在每个索引处从一个复制到另一个,如果该索引处已经有一个值,则认为存在冲突:
- 对于索引 #0,第一个列表中有 "a",第二个列表中有 "a"。我们通过选择第二个值来解决冲突(尽管在本例中它们是相同的)。所以索引 #0 得到 "a".
- 然后我们转到索引 #1,发现第一个列表有 "b",第二个列表有 "c"。我们通过选择第二个值来解决冲突,因此索引 #1 得到 "c".
- 现在对于索引 #2,我们没有冲突,因为只有第一个列表有值。我们将 "c" 保留在索引 #2 中,因此最终列表为 "a"、"c"、"c".
您可以改用集合,但它基本上执行联合操作,因此不会删除任何内容:
console.log(
Immutable.Set(['a', 'b', 'c'])
.mergeDeep(['a', 'c'])
);
// output: Set { "a", "b", "c" }
我实际上并不认为您要合并此列表...我认为您只是想将新值复制到旧值上。如果是这样,也许您只是在寻找 merge
而不是 mergeDeep
:
var state = Immutable.Map({
songTitle: '',
mainArtists: [],
featuredArtists: [],
releaseDate: '',
primaryGenre: '',
isExplicit: false,
labelName:'',
upCode: '',
eanCode: '',
isrcCode:'',
copyRight: ''
});
function doMerge(state, newState) {
// no deep merge here, just copy whatever fields are present in newState
return state.merge(newState);
}
console.log(state.get('mainArtists'));
// output: []
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'tyga']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "tyga" ]
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'tyga', 'john']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "tyga", "john" ]
state = doMerge(state, {
mainArtists: ['drake', 'rihanna', 'john']
});
console.log(state.get('mainArtists'));
// output: List [ "drake", "rihanna", "john" ]