我们已经知道,为了触发新的渲染,React 会根据类型和值比较状态变量 (
===
)。然而,当我们想要更新对象时,我们必须克隆内部的任何嵌套对象以避免改变实际对象,因此每次都在一个新副本上工作。
例如,假设我们有以下对象:
const [object, setObject] = useState({a: {b: {c: {a: 'a'}}}})
setObject(prev=>{...prev, {b: {...prev.b, c: {...prev.b.c, a: 'new value'}}}}
这意味着在这一点之前我必须克隆所有内容,因为任何对象在内存中都有自己的实际表示。
但是,如果执行以下操作:
object.b.c.a = 'new value'
setObject({...object})
它将触发渲染,因为对象的主要引用已更改。这有什么问题,使用它会发生什么?
我唯一能想到的是我不使用对象的前一个状态,如果我使用计时器,它可能会导致一些问题,因为它无法获取最近的状态。但总的来说,如果我不在这里使用定时器,有什么问题吗?
state
中的App
的变化不会影响value
中的
Child
import { useState } from "react";
export default function App() {
const [state, setState] = useState({ user: { name: "Alex" } });
const handleClick = () => {
setState({ ...state, user: { ...state.user, name: "Tom" } });
};
return (
<div className="App">
<button onClick={handleClick}>Click me</button>
<p>Your current name is: {state.user.name}</p>
<Child user={state.user} />
</div>
);
}
function Child({ user }) {
// assign props once
const [value, setValue] = useState(user);
// state doesn't change
return <p>Your previous name is: {value.name}</p>;
}
state
中App
的变化会影响value
中的Child
,尽管它不应该
import { useState } from "react";
export default function App() {
const [state, setState] = useState({ user: { name: "Alex" } });
const handleClick = () => {
state.user.name = "Tom";
setState({ ...state });
};
return (
<div className="App">
<button onClick={handleClick}>Click me</button>
<p>Your current name is: {state.user.name}</p>
<Child user={state.user} />
</div>
);
}
function Child({ user }) {
// assign props once
const [value, setValue] = useState(user);
// state changes although it shouldn't
return <p>Your previous name is: {value.name}</p>;
}
好吧,这是一个例子,说明在 React 状态下直接改变对象如何导致一些错误:
const [state, setState] = useState({count: 0, message: ''})
function handleClick() {
// Directly mutate the state object
state.count++
state.message = `Clicked ${state.count} times`
// Call setState with the mutated object
setState(state)
}
在这里,我们直接改变状态对象,然后用改变后的对象调用 setState()。
这可能会导致细微的错误,因为 React 出于性能原因将状态更新一起批处理。如果您直接更新一个状态变量,然后使用其他变量调用 setState(),React 可能不会按照您期望的顺序应用更新。 在这种情况下,React 可能会应用计数更新而不是消息更新。这可能会导致消息不反映当前计数的不一致状态。
为避免这些问题,最好始终使用 setState() 的函数形式并将先前状态作为参数传递。这可确保您始终使用最新状态,并确保以正确的顺序应用更新。
希望这对你有帮助,这适用于数组和对象。