Skip to content

Commit f64f32e

Browse files
[Docs]: Add mutation is unreliable and should be avoided
1 parent 2534424 commit f64f32e

File tree

3 files changed

+12
-6
lines changed

3 files changed

+12
-6
lines changed

src/content/learn/tutorial-tic-tac-toe.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ The DOM `<button>` element's `onClick` attribute has a special meaning to React
13371337
13381338
Note how in `handleClick`, you call `.slice()` to create a copy of the `squares` array instead of modifying the existing array. To explain why, we need to discuss immutability and why immutability is important to learn.
13391339
1340-
There are generally two approaches to changing data. The first approach is to _mutate_ the data by directly changing the data's values. The second approach is to replace the data with a new copy which has the desired changes. Here is what it would look like if you mutated the `squares` array:
1340+
In React, _mutating_ state directly doesn’t trigger re-renders because React cannot detect changes to the same object reference. To update state, you must replace the data with a new copy that has the desired changes. This _immutable_ update ensures React knows the state has changed and re-renders your component. Here is what it would look like if you mutated the `squares` array:
13411341
13421342
```jsx
13431343
const squares = [null, null, null, null, null, null, null, null, null];
@@ -1355,6 +1355,12 @@ const nextSquares = ['X', null, null, null, null, null, null, null, null];
13551355
13561356
The result is the same but by not mutating (changing the underlying data) directly, you gain several benefits.
13571357
1358+
<Note>
1359+
1360+
__Mutating state__ directly doesn't trigger re-renders. When you mutate an object or array in place, React cannot detect the change because the reference remains the same and due to that your component will not re-render.
1361+
1362+
</Note>
1363+
13581364
Immutability makes complex features much easier to implement. Later in this tutorial, you will implement a "time travel" feature that lets you review the game's history and "jump back" to past moves. This functionality isn't specific to games--an ability to undo and redo certain actions is a common requirement for apps. Avoiding direct data mutation lets you keep previous versions of the data intact, and reuse them later.
13591365
13601366
There is also another benefit of immutability. By default, all child components re-render automatically when the state of a parent component changes. This includes even the child components that weren't affected by the change. Although re-rendering is not by itself noticeable to the user (you shouldn't actively try to avoid it!), you might want to skip re-rendering a part of the tree that clearly wasn't affected by it for performance reasons. Immutability makes it very cheap for components to compare whether their data has changed or not. You can learn more about how React chooses when to re-render a component in [the `memo` API reference](/reference/react/memo).

src/content/learn/updating-arrays-in-state.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ Arrays are mutable in JavaScript, but you should treat them as immutable when yo
1818

1919
## Updating arrays without mutation {/*updating-arrays-without-mutation*/}
2020

21-
In JavaScript, arrays are just another kind of object. [Like with objects](/learn/updating-objects-in-state), **you should treat arrays in React state as read-only.** This means that you shouldn't reassign items inside an array like `arr[0] = 'bird'`, and you also shouldn't use methods that mutate the array, such as `push()` and `pop()`.
21+
In JavaScript, arrays are just another kind of object. [Like with objects](/learn/updating-objects-in-state), **you should treat arrays in React state as read-only.** Although JavaScript arrays are technically mutable, mutating them directly __(for example, with `arr[0] = 'bird'` or methods like `push() and pop()`)__ will not trigger a re‑render because React cannot detect the change.
2222

23-
Instead, every time you want to update an array, you'll want to pass a *new* array to your state setting function. To do that, you can create a new array from the original array in your state by calling its non-mutating methods like `filter()` and `map()`. Then you can set your state to the resulting new array.
23+
Instead, every time you want to update an array, you need to pass a *new* array to your __state setting function__. To do that, you can create a new array from the original array in your state by calling its non-mutating methods like `filter()` and `map()` or simply using spread operator `[ ... ]`. Then you can set your state to the resulting new array.
2424

2525
Here is a reference table of common array operations. When dealing with arrays inside React state, you will need to avoid the methods in the left column, and instead prefer the methods in the right column:
2626

src/content/learn/updating-objects-in-state.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Technically, it is possible to change the contents of _the object itself_. **Thi
4545
position.x = 5;
4646
```
4747

48-
However, although objects in React state are technically mutable, you should treat them **as if** they were immutable--like numbers, booleans, and strings. Instead of mutating them, you should always replace them.
48+
However, objects are technically **mutable**, but mutating them directly will not trigger **re-renders** because React cannot detect the change. Instead, always create a new object with the desired updates and replace the state with that new copy (Immutate object).
4949

5050
## Treat state as read-only {/*treat-state-as-read-only*/}
5151

@@ -104,7 +104,7 @@ onPointerMove={e => {
104104
}}
105105
```
106106

107-
This code modifies the object assigned to `position` from [the previous render.](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) But without using the state setting function, React has no idea that object has changed. So React does not do anything in response. It's like trying to change the order after you've already eaten the meal. While mutating state can work in some cases, we don't recommend it. You should treat the state value you have access to in a render as read-only.
107+
This code modifies the object assigned to `position` from [the previous render.](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) But without using the state setting function, React cannot detect that the object has changed, so no **re-render** occurs. So React does not do anything in response. It's like trying to change the order after you've already eaten the meal. Mutating state directly is unreliable and should be avoided. In React, always treat state as read-only and use the setter function to replace it with a new object when making updates.
108108

109109
To actually [trigger a re-render](/learn/state-as-a-snapshot#setting-state-triggers-renders) in this case, **create a *new* object and pass it to the state setting function:**
110110

@@ -804,7 +804,7 @@ There are a few reasons:
804804
* **Requirement Changes:** Some application features, like implementing Undo/Redo, showing a history of changes, or letting the user reset a form to earlier values, are easier to do when nothing is mutated. This is because you can keep past copies of state in memory, and reuse them when appropriate. If you start with a mutative approach, features like this can be difficult to add later on.
805805
* **Simpler Implementation:** Because React does not rely on mutation, it does not need to do anything special with your objects. It does not need to hijack their properties, always wrap them into Proxies, or do other work at initialization as many "reactive" solutions do. This is also why React lets you put any object into state--no matter how large--without additional performance or correctness pitfalls.
806806

807-
In practice, you can often "get away" with mutating state in React, but we strongly advise you not to do that so that you can use new React features developed with this approach in mind. Future contributors and perhaps even your future self will thank you!
807+
In practice, **mutating** state fundamentally prevents _React_ from detecting a change and triggering a **re-render**. For this reason, we strongly advise you _never_ to mutate state. Following the immutability rule ensures your components are reliable and avoids hard-to-debug issues. Future contributors and perhaps even your future self will thank you!
808808

809809
</DeepDive>
810810

0 commit comments

Comments
 (0)