【问题标题】:Does React make a clone of your object when you use the set function?当你使用 set 函数时,React 会克隆你的对象吗?
【发布时间】:2021-08-22 18:44:26
【问题描述】:

我试图避免直接修改状态,所以我使用 lodash cloneDeep(),然后使用克隆设置状态。但是,我想进行额外的更改(在异步请求之后)并再次设置状态。在我将我的克隆传递给 set 函数之后,是否可以继续对该克隆进行更改?为了安全起见,我是否需要重新克隆我的克隆,或者 React 是否会克隆我的克隆?该代码可能有助于解释问题:

const [user, setUser] = useState({ name: '', email: '' })

const newUser = cloneDeep(user) // cloning to avoid modifying state directly
newUser.name = 'Steve' // setting a property on the clone
setUser(newUser) // all good up to this point

// some async stuff happens, then later:

newUser.email = 'steve@example.com' // still modifying the clone, but is this safe?
setUser(newUser)

由于我修改了之前使用 setUser 传递的克隆,那只是直接修改状态吗?

当我调用setUser() 时,我试图检查 React 源代码以确定它们是否在进行克隆,但我无法理解发生了什么。 :)

【问题讨论】:

    标签: javascript reactjs react-hooks lodash


    【解决方案1】:
    newUser.email = 'steve@example.com' // still modifying the clone, but is this safe?
    setUser(newUser)
    

    我认为这不是一个好主意。 newUser 与您在上一次调用setUser 时使用的引用相同(在异步请求之前),因此实际上可能在bail 中做出反应,因为它与您在上一次调用期间使用的值相同到setState

    你的情况也和这个一样

    let user = {};
    setUser(user);
    user.a=1;
    

    在以下意义上:一旦我在第 2 步将user 传递给setUser,无论它是全新的对象还是我之前克隆的东西都没有关系,重点在于第 3 步我正在修改我在第 2 步中传递给 setUser 的内容。在我看来,这确实像是在修改处于状态的东西。


    所以第二次尝试以 immutable 的方式更新状态。大多数情况下,使用... 使用浅拷贝进行不可变状态更新对我有用(如果你做得对的话),所以你可以避免额外的库。

    【讨论】:

    • 谢谢!这很有意义,我现在只是使用嵌套扩展运算符来避免创建多个克隆。我确实遇到了它不会重新渲染的问题,现在我知道这是由于您提到的保释功能。
    【解决方案2】:

    我会简化一下:

    const [user, setUser] = useState({ name: '', email: '' })
    
    // spread and create a new object
    // and append the new property  
    const newUser = { …user, name: “Steve” }
    
    setUser(newUser)
    
    // Async call happens
    
    // spread and create a new object
    // and append the new property
    setUser({ …newUser, email: “steve@example.com” })
    

    只需使用扩展运算符。

    我不确定先设置名称然后设置 emsil 的原因是什么,但为什么不先调用并完全设置用户呢?这样您就不必担心上述任何问题。它也会节省渲染周期。

    【讨论】:

    • 谢谢,这是一个人为的例子,在实际功能中,我正在做一些验证,需要调用服务器,然后设置其他属性,所以这很有意义,但我试图简化这个例子的代码。另外,我使用cloneDeep() 的原因是在我的真实函数中我有一个很大的嵌套对象。无论如何,我现在只是在做嵌套传播。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 2010-11-08
    • 2016-10-02
    相关资源
    最近更新 更多