我无法理解为什么当向量中有对象时,在复制向量时不会创建对它们的新引用。
但是问题就在这里。
const USERS_TYPE = [
{name:"User",icon:faTruck,
inputs:[
{label:"Name",required:true,width:"200px",value:"", error:false},
{label:"ID",required:true,width:"150px",value:"", error:false},
{label:"Email",required:false,width:"150px",value:"", error:false},
]}]
我尝试通过两种方式将此向量传递给状态。
const [users,setUsers] = useState(USERS_TYPE.map(item=>({...item})))
const [users,setUsers] = useState([...USERS_TYPE])
在这两种情况下,使用 setUser 更改用户都会更改 USERS_TYPE。
我改变的方式之一。
const changes = [...users]
const err = validation(changes[selected-1].inputs)
err.map((index)=>{
changes[selected-1].inputs[index].error = true
})
setUsers(changes)
我能想出什么解决方案,从向量更改为对象,另一种复制机制。 此副本没有多大意义,因为内部对象引用保持不变。
编辑:另一个重要的细节是 USER_TYPE 位于函数组件之外。
最佳答案
it doesn't create new references to them when copying the vector
因为这不是 JS 的工作方式。它不会自动深度克隆内容。
const user1 = {id:1}
const user2 = {id:2}
const users = [user1,user2];
const newUsers = [...users]; // this clones users, BUT NOT the objects it contains
console.log(newUsers === users); // false, it's a new array
console.log(newUsers[0] === users[0]) // true, it's the same reference
最终,你只是在改变状态。 React 的首要也是最重要的黄金法则:不要改变状态。
这是导致错误的行:
err.map((index)=>{
// you are mutating an object by doing this
// yes, `changes` is a new array, but you are still mutating the object that is part of state that is nested inside of that array
changes[selected-1].inputs[index].error = true
})
也许这会起作用:
const idx = selected-1;
const err = validation(users[idx].inputs)
setUsers(users => users.map((user,i) => {
if(i !== idx) return user; // you aren't interested in this user, leave it unmodified
// you need to change the inputs for this user
// first, shallow clone the object using the spread operator
return {
...user,
// now inputs must be a new reference as well, so clone it using map
inputs: user.inputs.map((input,index) => ({
// careful not to mutate the input object, clone it using spread
...input,
// and set the error property on the cloned object
error: !!err[index]
}))
}
}))
编辑:对所有代码编辑表示抱歉,我有很多语法错误。我试图表达的最终观点仍然是一致的。
编辑#2:
Another important detail is that the USER_TYPE is outside the function component.
在这种情况下这并不重要,因为它是您的初始状态。每次更新状态时,您都需要以不变的方式进行操作(如我上面所示),以免改变此全局对象。如果你真的改变它,你会发现通过卸载组件并重新安装组件将导致看起来像“保留状态”的结果 - 但这只是你改变了用作初始状态模板的全局对象。
关于javascript - 复制对象数组以用作状态 - React.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69268846/