我在useState
:中有以下对象
const [obj, setObj] = React.useState({
one: {
index: "one",
name: "Number one"
},
two: {
index: "two",
name: "Number two"
}
});
我想要的是在一次调用中更新index
或name
。我有这个:
function update(from, what, value) {
const objTemp = {...obj};
obj[from][what] = value;
setObj(objTemp);
}
我把这个函数称为:update('one', 'index', 'Hey')
或update('two', 'name', 'Foo')
。我一直在尝试,我可以处理这种情况:
const [x, setX] = React.useState({ one: 'One', two: 'Two' });
function updt(from, value) {
setX({...x, [from]: value});
}
但我无法找到一种方法来优化我的第一个函数,就像上一个一样。我试过了:
setObj({...obj, [from][what]: value});
但这肯定没有奏效。有什么方法可以优化我的update
函数,使其看起来像我的updt
函数吗?
您已经接近了,基本上您需要对正在更新的嵌套对象进行第二次对象扩展/变异。
setObj({...obj, [from]: { ...obj[from], [what]: value} });
注意:您仍然在肤浅地复制整个对象,即每个无数的属性,因此从技术上讲,这与您已经拥有/拥有的一样有效。(也许更少,因为现在有两个排列操作!!(
也有人可能会说,它现在的可读性也有点低,现在只剩下一行了。
react状态更新的重要步骤是始终返回新对象引用的纯函数范式,这是初始对象扩散的原因。
我还应该注意,不建议将复杂对象存储在useState
挂钩中,正是因为这个原因,使用深度嵌套的更新来维护正确的状态更新要多得多。useReducer
通常被推荐用于这些情况。存在同样的更新复杂性,但这是一种更清晰的模式。
const obj = {
one: {
index: "one",
name: "Number one"
},
two: {
index: "two",
name: "Number two"
}
};
function update(from, what, value) {
return {...obj, [from]: { ...obj[from], [what]: value} };
}
console.log(update('one', 'name', 'Number 1'))
对于这样的复杂状态,您不应该使用state,只需尝试使用Reducer
const initialState = {
one: {
index: "one",
name: "Number one"
},
two: {
index: "two",
name: "Number two"
}
};
function reducer(state, action) {
switch (action.type) {
case 'update':
const { property, subProperty, value } = actions.payload
const newState = {
...state,
[property]: {
...state[property],
[subProperty]: value
}
}
return newState;
default:
throw new Error();
}
}
然后你可以把它和一起使用
dispatch({type: 'update', payload: {"one", "name", "Number 1"})