You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/learn/you-might-not-need-an-effect.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -408,7 +408,7 @@ function Game() {
408
408
409
409
There are two problems with this code.
410
410
411
-
First problem is that it is very inefficient: the component (and its children) have to re-render between each `set` call in the chain. In the example above, in the worst case (`setCard` → render → `setGoldCardCount` → render → `setRound` → render → `setIsGameOver` → render) there are three unnecessary re-renders of the tree below.
411
+
The first problem is that it is very inefficient: the component (and its children) have to re-render between each `set` call in the chain. In the example above, in the worst case (`setCard` → render → `setGoldCardCount` → render → `setRound` → render → `setIsGameOver` → render) there are three unnecessary re-renders of the tree below.
412
412
413
413
The second problem is that even if it weren't slow, as your code evolves, you will run into cases where the "chain" you wrote doesn't fit the new requirements. Imagine you are adding a way to step through the history of the game moves. You'd do it by updating each state variable to a value from the past. However, setting the `card` state to a value from the past would trigger the Effect chain again and change the data you're showing. Such code is often rigid and fragile.
Copy file name to clipboardExpand all lines: src/content/reference/react/lazy.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -78,7 +78,7 @@ Now that your component's code loads on demand, you also need to specify what sh
78
78
<Suspense fallback={<Loading />}>
79
79
<h2>Preview</h2>
80
80
<MarkdownPreview />
81
-
</Suspense>
81
+
</Suspense>
82
82
```
83
83
84
84
In this example, the code for `MarkdownPreview` won't be loaded until you attempt to render it. If `MarkdownPreview` hasn't loaded yet, `Loading` will be shown in its place. Try ticking the checkbox:
Copy file name to clipboardExpand all lines: src/content/reference/react/useMemo.md
+77Lines changed: 77 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1056,6 +1056,83 @@ Keep in mind that you need to run React in production mode, disable [React Devel
1056
1056
1057
1057
---
1058
1058
1059
+
### Preventing an Effect from firing too often {/*preventing-an-effect-from-firing-too-often*/}
1060
+
1061
+
Sometimes, you might want to use a value inside an [Effect:](/learn/synchronizing-with-effects)
1062
+
1063
+
```js {4-7,10}
1064
+
functionChatRoom({ roomId }) {
1065
+
const [message, setMessage] =useState('');
1066
+
1067
+
constoptions= {
1068
+
serverUrl:'https://localhost:1234',
1069
+
roomId: roomId
1070
+
}
1071
+
1072
+
useEffect(() => {
1073
+
constconnection=createConnection(options);
1074
+
connection.connect();
1075
+
// ...
1076
+
```
1077
+
1078
+
This creates a problem. [Every reactive value must be declared as a dependency of your Effect.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) However, if you declare `options` as a dependency, it will cause your Effect to constantly reconnect to the chat room:
1079
+
1080
+
1081
+
```js {5}
1082
+
useEffect(() => {
1083
+
constconnection=createConnection(options);
1084
+
connection.connect();
1085
+
return () =>connection.disconnect();
1086
+
}, [options]); // 🔴 Problem: This dependency changes on every render
1087
+
// ...
1088
+
```
1089
+
1090
+
To solve this, you can wrap the object you need to call from an Effect in `useMemo`:
1091
+
1092
+
```js {4-9,16}
1093
+
functionChatRoom({ roomId }) {
1094
+
const [message, setMessage] =useState('');
1095
+
1096
+
constoptions=useMemo(() => {
1097
+
return {
1098
+
serverUrl:'https://localhost:1234',
1099
+
roomId: roomId
1100
+
};
1101
+
}, [roomId]); // ✅ Only changes when roomId changes
1102
+
1103
+
useEffect(() => {
1104
+
constoptions=createOptions();
1105
+
constconnection=createConnection(options);
1106
+
connection.connect();
1107
+
return () =>connection.disconnect();
1108
+
}, [options]); // ✅ Only changes when createOptions changes
1109
+
// ...
1110
+
```
1111
+
1112
+
This ensures that the `options` object is the same between re-renders if `useMemo` returns the cached object.
1113
+
1114
+
However, since `useMemo` is performance optimization, not a semantic guarantee, React may throw away the cached value if [there is a specific reason to do that](#caveats). This will also cause the effect to re-fire, **so it's even better to remove the need for a function dependency** by moving your object *inside* the Effect:
1115
+
1116
+
```js {5-8,13}
1117
+
functionChatRoom({ roomId }) {
1118
+
const [message, setMessage] =useState('');
1119
+
1120
+
useEffect(() => {
1121
+
constoptions= { // ✅ No need for useMemo or object dependencies!
1122
+
serverUrl:'https://localhost:1234',
1123
+
roomId: roomId
1124
+
}
1125
+
1126
+
constconnection=createConnection(options);
1127
+
connection.connect();
1128
+
return () =>connection.disconnect();
1129
+
}, [roomId]); // ✅ Only changes when roomId changes
1130
+
// ...
1131
+
```
1132
+
1133
+
Now your code is simpler and doesn't need `useMemo`. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
1134
+
1135
+
1059
1136
### Memoizing a dependency of another Hook {/*memoizing-a-dependency-of-another-hook*/}
1060
1137
1061
1138
Suppose you have a calculation that depends on an object created directly in the component body:
0 commit comments