我有一些尝试更新特定状态的通用代码。可以通过数组中的键访问对象,例如:
let x = {person: { name: "Dennis"}}
console.log(x["person"]["name"])
在反应中,可以(通常用于输入验证)通过数组访问特定的状态键,例如:
//event.target.name = input field property name="firstName"
this.setState({
[event.target.name]: event.target.value
});
将this.state.firstName
更新为输入值。
我正在尝试将嵌套的复杂对象绑定到输入,以避免具有转换功能。因此,如果我的州包含{ person: {name : "" } }
,我想通过this.state动态访问它[" person"] [" name"] - 这有效。我想在setState
中使用相同的表示法,因为我可以将嵌套的状态数据绑定到这样的输入:<input name="person.name" />
并且在我的更改处理程序中我可以查找句点:if(ev.target.name.split("."))...
但是,我似乎无法在setState中以相同的方式访问状态,因为它是一个对象,所以:
const args = ev.target.name.split(".");
this.setState({
[args[0]][args[1]]: ev.target.value
});
有没有这样做?
答案 0 :(得分:1)
事实证明这比最初想象的要复杂一些。通过使用Object.assign,所有嵌套对象都保留了它们的不可变属性,这使得无法更改它们。我不得不制作一份国家的硬拷贝,以便改变它。使用lodash.set中的_set可以在很少的行中完成:
//Create a hard-copy of the state
let stateCopy = JSON.parse(JSON.stringify(this.state));
//Update the value in the state with the input value
_set(stateCopy, ev.target.name, ev.target.value);
//Set the state with the changed value
this.setState(stateCopy);
编辑:唯一的缺点是目前我在setState()中复制整个状态而不仅仅是delta值。
答案 1 :(得分:0)
我喜欢使用ramda。 它看起来像
this.setState(R.assocPath(args, ev.target.value))
答案 2 :(得分:0)
它有点复杂,你可以深层复制对象:
const args = ev.target.name.split(".");
let result = {};
const root = result;
let pos = this.state;
const last = args.pop();
for(const arg of args) {
Object.assign(result, pos);
result = result[arg] || (result[arg] = {});
pos = pos[arg] || {};
}
result[last] = evt.target.value;
this.setState(root);