Skip to content

Commit cffb6a7

Browse files
authored
Specify that Effects run on commit, not render (#8162)
1 parent e22544e commit cffb6a7

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

src/content/reference/react/useEffect.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ function ChatRoom({ roomId }) {
4444
4545
#### Parameters {/*parameters*/}
4646
47-
* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your component is added to the DOM, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. After your component is removed from the DOM, React will run your cleanup function.
47+
* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. When your [component commits](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom), React will run your setup function. After every commit with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. After your component is removed from the DOM, React will run your cleanup function.
4848
49-
* **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If you omit this argument, your Effect will re-run after every re-render of the component. [See the difference between passing an array of dependencies, an empty array, and no dependencies at all.](#examples-dependencies)
49+
* **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If you omit this argument, your Effect will re-run after every commit of the component. [See the difference between passing an array of dependencies, an empty array, and no dependencies at all.](#examples-dependencies)
5050
5151
#### Returns {/*returns*/}
5252
@@ -107,14 +107,14 @@ You need to pass two arguments to `useEffect`:
107107
**React calls your setup and cleanup functions whenever it's necessary, which may happen multiple times:**
108108
109109
1. Your <CodeStep step={1}>setup code</CodeStep> runs when your component is added to the page *(mounts)*.
110-
2. After every re-render of your component where the <CodeStep step={3}>dependencies</CodeStep> have changed:
110+
2. After every commit of your component where the <CodeStep step={3}>dependencies</CodeStep> have changed:
111111
- First, your <CodeStep step={2}>cleanup code</CodeStep> runs with the old props and state.
112112
- Then, your <CodeStep step={1}>setup code</CodeStep> runs with the new props and state.
113113
3. Your <CodeStep step={2}>cleanup code</CodeStep> runs one final time after your component is removed from the page *(unmounts).*
114114
115115
**Let's illustrate this sequence for the example above.**
116116
117-
When the `ChatRoom` component above gets added to the page, it will connect to the chat room with the initial `serverUrl` and `roomId`. If either `serverUrl` or `roomId` change as a result of a re-render (say, if the user picks a different chat room in a dropdown), your Effect will *disconnect from the previous room, and connect to the next one.* When the `ChatRoom` component is removed from the page, your Effect will disconnect one last time.
117+
When the `ChatRoom` component above gets added to the page, it will connect to the chat room with the initial `serverUrl` and `roomId`. If either `serverUrl` or `roomId` change as a result of a commit (say, if the user picks a different chat room in a dropdown), your Effect will *disconnect from the previous room, and connect to the next one.* When the `ChatRoom` component is removed from the page, your Effect will disconnect one last time.
118118
119119
**To [help you find bugs,](/learn/synchronizing-with-effects#step-3-add-cleanup-if-needed) in development React runs <CodeStep step={1}>setup</CodeStep> and <CodeStep step={2}>cleanup</CodeStep> one extra time before the <CodeStep step={1}>setup</CodeStep>.** This is a stress-test that verifies your Effect's logic is implemented correctly. If this causes visible issues, your cleanup function is missing some logic. The cleanup function should stop or undo whatever the setup function was doing. The rule of thumb is that the user shouldn't be able to distinguish between the setup being called once (as in production) and a *setup* → *cleanup* → *setup* sequence (as in development). [See common solutions.](/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development)
120120
@@ -1145,7 +1145,7 @@ useEffect(() => {
11451145
11461146
#### Passing a dependency array {/*passing-a-dependency-array*/}
11471147
1148-
If you specify the dependencies, your Effect runs **after the initial render _and_ after re-renders with changed dependencies.**
1148+
If you specify the dependencies, your Effect runs **after the initial commit _and_ after commits with changed dependencies.**
11491149
11501150
```js {3}
11511151
useEffect(() => {
@@ -1242,7 +1242,7 @@ button { margin-left: 5px; }
12421242
12431243
#### Passing an empty dependency array {/*passing-an-empty-dependency-array*/}
12441244
1245-
If your Effect truly doesn't use any reactive values, it will only run **after the initial render.**
1245+
If your Effect truly doesn't use any reactive values, it will only run **after the initial commit.**
12461246
12471247
```js {3}
12481248
useEffect(() => {
@@ -1319,7 +1319,7 @@ export function createConnection(serverUrl, roomId) {
13191319
13201320
#### Passing no dependency array at all {/*passing-no-dependency-array-at-all*/}
13211321
1322-
If you pass no dependency array at all, your Effect runs **after every single render (and re-render)** of your component.
1322+
If you pass no dependency array at all, your Effect runs **after every single commit** of your component.
13231323
13241324
```js {3}
13251325
useEffect(() => {
@@ -1480,7 +1480,7 @@ Now that you're passing `c => c + 1` instead of `count + 1`, [your Effect no lon
14801480
14811481
### Removing unnecessary object dependencies {/*removing-unnecessary-object-dependencies*/}
14821482
1483-
If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every render because the `options` object is [different for every render:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally)
1483+
If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every commit because the `options` object is [different for every render:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally)
14841484
14851485
```js {6-9,12,15}
14861486
const serverUrl = 'https://localhost:1234';
@@ -1497,7 +1497,7 @@ function ChatRoom({ roomId }) {
14971497
const connection = createConnection(options); // It's used inside the Effect
14981498
connection.connect();
14991499
return () => connection.disconnect();
1500-
}, [options]); // 🚩 As a result, these dependencies are always different on a re-render
1500+
}, [options]); // 🚩 As a result, these dependencies are always different on a commit
15011501
// ...
15021502
```
15031503
@@ -1583,7 +1583,7 @@ With this fix, typing into the input doesn't reconnect the chat. Unlike an objec
15831583
15841584
### Removing unnecessary function dependencies {/*removing-unnecessary-function-dependencies*/}
15851585
1586-
If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every render because the `createOptions` function is [different for every render:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally)
1586+
If your Effect depends on an object or a function created during rendering, it might run too often. For example, this Effect re-connects after every commit because the `createOptions` function is [different for every render:](/learn/removing-effect-dependencies#does-some-reactive-value-change-unintentionally)
15871587
15881588
```js {4-9,12,16}
15891589
function ChatRoom({ roomId }) {
@@ -1601,11 +1601,11 @@ function ChatRoom({ roomId }) {
16011601
const connection = createConnection();
16021602
connection.connect();
16031603
return () => connection.disconnect();
1604-
}, [createOptions]); // 🚩 As a result, these dependencies are always different on a re-render
1604+
}, [createOptions]); // 🚩 As a result, these dependencies are always different on a commit
16051605
// ...
16061606
```
16071607
1608-
By itself, creating a function from scratch on every re-render is not a problem. You don't need to optimize that. However, if you use it as a dependency of your Effect, it will cause your Effect to re-run after every re-render.
1608+
By itself, creating a function from scratch on every re-render is not a problem. You don't need to optimize that. However, if you use it as a dependency of your Effect, it will cause your Effect to re-run after every commit.
16091609
16101610
Avoid using a function created during rendering as a dependency. Instead, declare it inside the Effect:
16111611
@@ -1775,7 +1775,7 @@ First, check that you haven't forgotten to specify the dependency array:
17751775
```js {3}
17761776
useEffect(() => {
17771777
// ...
1778-
}); // 🚩 No dependency array: re-runs after every render!
1778+
}); // 🚩 No dependency array: re-runs after every commit!
17791779
```
17801780
17811781
If you've specified the dependency array but your Effect still re-runs in a loop, it's because one of your dependencies is different on every re-render.

src/content/reference/react/useLayoutEffect.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ function Tooltip() {
4747
4848
#### Parameters {/*parameters*/}
4949
50-
* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. Before your component is added to the DOM, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. Before your component is removed from the DOM, React will run your cleanup function.
50+
* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. Before your [component commits](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom), React will run your setup function. After every commit with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. Before your component is removed from the DOM, React will run your cleanup function.
5151
52-
* **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If you omit this argument, your Effect will re-run after every re-render of the component.
52+
* **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If you omit this argument, your Effect will re-run after every commit of the component.
5353
5454
#### Returns {/*returns*/}
5555

0 commit comments

Comments
 (0)