我有这样的嵌套状态:
this.state = {
fields: {
subject: '',
from: {
name: '',
},
},
};
在onChange
函数中,我正在处理对这些嵌套值的更新。
我正在尝试使用点表示法为深层嵌套动态分布setState()
。
例如,使用数组:const tree = ['fields','subject']
,我可以使用以下命令更新subject
状态值:
this.setState(prevState => ({
[tree[0]]: {
...prevState[tree[0]],
...(tree[2] ? {
...prevState[tree[1]],
[tree[2]]: value
}
: { [tree[1]]: value })
},
}));
由于三元运算符以{ [tree[1]]: value }
结尾
但是当我的tree
数组是:const tree = ['fields','from','name']
时,fields.from.name
的状态值没有改变,它应该解析为三元运算符的第一部分:
{
...prevState[tree[1]],
[tree[2]]: value
}
我想念什么吗?
答案 0 :(得分:3)
当我感觉自己正在重新发明轮子时,我已经越来越喜欢使用库来实现这些功能。 lodash提供了set
函数(它还支持字符串路径):
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4
_.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object.x[0].y.z);
// => 5
您还希望使用_.cloneDeep(value)
,因为_.set
会改变对象。
this.state = {
fields: {
subject: '',
from: { name: '' },
},
};
const tree = ['fields', 'from', 'name']; // or 'fields.from.name'
this.setState(prevState => {
const prevState_ = _.cloneDeep(prevState);
return _.set(prevState_, tree, value);
});
答案 1 :(得分:2)
您将需要一个循环。例如:
function update(prevState, tree, value) {
const newState = {};
let obj = newState;
for (let i = 0; i < tree.length; ++i) {
const name = tree[i];
if (i === tree.length - 1) {
obj[name] = value;
} else {
obj = obj[name] = {...prevState[name]};
}
}
return newState;
}
实时示例:
this.state = {
fields: {
subject: '',
from: {
name: '',
},
},
};
function update(prevState, tree, value) {
const newState = {};
let obj = newState;
let prev = prevState;
for (let i = 0; i < tree.length; ++i) {
const name = tree[i];
if (i === tree.length - 1) {
obj[name] = value;
} else {
const nextPrev = prev[name];
obj = obj[name] = {...nextPrev};
prev = nextPrev;
}
}
return newState;
}
const tree = ['fields','from','name']
const value = "updated";
console.log(update(this.state, tree, value));
我敢肯定,可以调用Array#reduce
(因为可以执行任何数组操作),但是它不会给您带来任何好处。