因此,我花了数十个小时来思考为什么此时会发生这种情况,并且我研究了几种不同的解决方案。
尽管我已经进行了彻底的研究,但我很确定它与React的setState函数的任何生命周期方法或异步问题都没有关系。
我很确定这与tempState实际改变状态的值/引用问题无关,因为我使用lodash来深度克隆状态对象,尽管这是先前的问题。
我怀疑这与setState的浅表合并有关,但是我无法一生找出原因。
从本质上讲,我认为这段代码仅应更改typeAheadOptions数组以将hostshow
的值更改为Various Shows
,但它也在使状态发生变化,并且甚至没有相同的方式。状态甚至与typeAheadOptions都不一样,它的状态更深,其中还包含其他几层。
在这一点上,我可能会用Redux和ImmutableJS重建它,但是现在我真的需要了解为什么会这样,因为它使我有些疯狂。现在,我阅读了一些建议,以使您的状态对象尽可能平整,我想我现在明白为什么。
这里是仅包含相关位的摘录状态:
this.state = {
showByName: false,
showByShow: true,
resources: [
{
show: "TED Radio Hour",
showurl: TEDRadioHour,
hosts: [
{
firstName: "Guy",
lastName: "Raz",
personurl: GuyRaz,
hostshow: "TED Radio Hour"
}
]
},
{
show: "Radiolab",
showurl: Radiolab,
hosts: [
{
firstName: "Jad",
lastName: "Abumrad",
personurl: JadAbumrad,
hostshow: "Radiolab"
},
{
firstName: "Robert",
lastName: "Krulwich",
personurl: RobertKrulwich,
hostshow: "Radiolab"
}
]
},
{
show: "How I Built This",
showurl: HowIBuiltThis,
hosts: [
{
firstName: "Guy",
lastName: "Raz",
personurl: GuyRaz,
hostshow: "How I Built This"
}
]
},
{
show: "Radiolab Presents: More Perfect",
showurl: RadiolabPresentsMorePerfect,
hosts: [
{
firstName: "Jad",
lastName: "Abumrad",
personurl: JadAbumrad,
hostshow: "Radiolab Presents: More Perfect"
}
]
}
],
contentToRender: [],
typeAheadOptions: [],
selected: [],
duplicateHostIndices: []
}
}
这是函数:
showByName() {
const tempState = _.cloneDeep(this.state);
tempState.showByName = true;
tempState.showByShow = false;
tempState.selected.length = 0;
this.alphabetizeHostList(tempState);
}
alphabetizeHostList(tempState) { // sorting state so that results are alphabetical
tempState.typeAheadOptions.length = 0; // clear typeAhead options
tempState.resources.forEach((resource, index) => {
resource.hosts.forEach((host, index) => {
tempState.typeAheadOptions.push(host);
tempState.typeAheadOptions.sort(function(a, b) { // sorting function
var nameA = a.firstName.toUpperCase(); // ignore upper and lowercase
var nameB = b.firstName.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
})
})
this.populateDuplicateHostIndices(tempState);
}
populateDuplicateHostIndices(tempState) { // removes duplicates by first and last name for instances like Guy Raz and Jad Abumrad
let duplicateHostIndices = tempState.duplicateHostIndices;
duplicateHostIndices.length = 0;
let options = tempState.typeAheadOptions;
let length = options.length;
let i = 1;
if (length > 1 && tempState.showByName === true) {
for (i; i < length; i++) { // iterates over the hosts and finds duplicates by first and last name
if ((options[i - 1].firstName === options[i].firstName) && (options[i - 1].lastName === options[i].lastName)) {
duplicateHostIndices.push(i);
}
}
}
this.removeDuplicateHosts(tempState, duplicateHostIndices);
}
removeDuplicateHosts(tempState, duplicateHostIndices) {
if (duplicateHostIndices.length > 0) {
duplicateHostIndices.sort().reverse(); // if we didn't sort and reverse, we would remove the 1st host and the index of the rest would be off and we would remove them
duplicateHostIndices.forEach((element) => {
const previousElement = (element - 1);
tempState.typeAheadOptions[(previousElement)].hostshow = "Various Shows";
tempState.typeAheadOptions.splice(element, 1);
});
}
this.pullContentToRenderFromTypeAheadList(tempState);
}
pullContentToRenderFromTypeAheadList(tempState) {
tempState.contentToRender = _.cloneDeep(tempState.typeAheadOptions); // separates out content that renders from list that TypeAhead pulls from
this.setState(tempState);
}
答案 0 :(得分:0)
Reactiflux上的某位人士指出,通过使用forEach()遍历我的状态对象并运行push()以形成一个新的tempState,实际上,我实际上是在直接改变我的原始状态,而不是像我以前假设的那样是一个新的tempState
这不是setState浅合并问题,而是像我以前认为已经解决的值/引用问题。
我仅通过调用带有部分状态的setState来解决此问题,因此永远没有机会覆盖我的原始真相。
现在要对过度嵌套的状态对象进行一些重构,并将此代码重构为更加简洁。