React中使用可变对象时,仅在状态变化时调用setState为何能避免不必要重渲染?
setState() Avoids Unnecessary Re-Renders with Mutable Objects Great question—let’s break this down with practical examples and React’s core behavior in mind.
First, let’s recap React’s default rule: any call to setState() will trigger a re-render, unless you explicitly return false from shouldComponentUpdate(). For class components, shouldComponentUpdate() returns true by default, so even if you pass the exact same state to setState(), React will still re-render the component and its children.
Now, let’s talk about mutable objects (like plain JS objects or arrays that you modify directly, e.g., this.state.users.push(newUser) or this.state.user.name = "New Name"). The key issue here is that when you mutate an object, its reference in memory doesn’t change. For example:
// Initial state this.state = { user: { name: "Alice" } }; // Mutate the existing object const currentUser = this.state.user; currentUser.name = "Bob"; // This changes the object's content, but not its reference
If you immediately call setState({ user: currentUser }) here, you’re passing the exact same object reference that’s already in state. But React doesn’t deep-compare state objects by default—it just sees that you called setState() and triggers a re-render, even though the only difference is the internal value of the mutable object.
Here’s why checking for differences first helps:
- When you modify a mutable object, you can compare its new values to the old state’s values (e.g., check if
currentUser.nameis actually different fromthis.state.user.name). - Only if those values are different do you call
setState(). This skips thesetState()call entirely when nothing has changed, which in turn skips the unnecessary re-render.
Let’s contrast this with immutable updates (like using spread syntax or libraries like Immer). With immutable objects, you create a new reference every time you update state:
const newUser = { ...this.state.user, name: "Bob" }; this.setState({ user: newUser });
Here, newUser is a brand new object with a new reference. Tools like PureComponent or React.memo can use shallow comparison to skip re-renders if the new state reference is the same as the old one—but this only works with immutable updates. If you’re stuck using mutable objects (and can’t implement custom shouldComponentUpdate() logic to deep-compare state), your only option is to manually check for value changes before calling setState().
To put it simply: By checking if the mutable object’s content has actually changed before calling setState(), you avoid triggering React’s default re-render behavior when there’s no meaningful change to the component’s state.
内容的提问来源于stack exchange,提问作者krave

