当你使用 set 函数时,React 会克隆你的对象吗?

Does React make a clone of your object when you use the set function?

我试图避免直接修改状态,所以我使用 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 源代码以确定它们是否在进行克隆,但我无法理解发生了什么。 :)

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

我认为这不是个好主意。 newUser 与您在之前对 setUser 的调用(在异步请求之前)中使用的引用相同,因此实际上 React 可能 bail 来自此 setState 因为它与您在之前调用 setState.

期间使用的值

你的情况也和这个一样

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

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


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

我会简化这个:

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” })

只需使用展开运算符即可。

我不知道为什么先设置name再设置emsil,但为什么不先调用再setUser呢?这样您就不必担心以上任何问题。它也将节省一个渲染周期。