javascript - 复制对象数组以用作状态 - React.js

标签 javascript reactjs

我无法理解为什么当向量中有对象时,在复制向量时不会创建对它们的新引用。

但是问题就在这里。

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/

相关文章:

javascript - speechSynthesis.getVoices() 在 Windows 上返回空数组

javascript - 预输入/预测测试功能遇到问题

javascript - 运行 create react app 时未定义“render”

javascript - 为什么 gtag 事件没有出现在 Google Analytics(分析)中?

javascript - 使用 jQuery 将事件绑定(bind)到表格单元格

javascript - 如何在 Selenium 中获取 javascript 工具提示消息?

javascript - 你如何将 Prop 传递给所有反应路线? (动态更改标题)

reactjs - Object(...) 不是 applyMiddleware(thunk.withExtraArgument({ getFirebase, getFirestore })) 的函数错误

reactjs - React Query 处理响应状态代码

javascript - Dojo datagrid - 检索每列字段的值。