Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
b440d66
fix(links): update internal links (#8136)
okeken Nov 10, 2025
27576f1
fix(useTransition): correct anchors pointing to non-blocking updates …
SecondThundeR Nov 14, 2025
2534424
fix: Stop SmartyPants from altering TerminalBlock commands (like `--s…
smikitky Nov 15, 2025
4704ce6
blog post (#8170)
rickhanlonii Dec 3, 2025
9c880bd
fix: use correct function name (#8171)
FelixTraxler Dec 3, 2025
e2b59da
add update instructions (#8172)
rickhanlonii Dec 3, 2025
0828d50
Update React releases (#8173)
eps1lon Dec 3, 2025
ac47e52
Update upgrade instructions for React Server Components (Waku section…
dai-shi Dec 4, 2025
d8b1fe8
Upgrade Next from 15.1.0 to 15.1.9 (#8175)
mattcarrollcode Dec 4, 2025
5876ed5
blog: update RSC security vulnerability guidance for Expo (#8177)
vonovak Dec 5, 2025
e22544e
Add Vulnerability in React Server Components to sidebarBlog.json (#8178)
SSakutaro Dec 5, 2025
cffb6a7
Specify that Effects run on commit, not render (#8162)
eps1lon Dec 11, 2025
2a0fed0
12/11 blog post (#8193)
rickhanlonii Dec 11, 2025
1a955f0
rm localhost link (#8194)
rickhanlonii Dec 11, 2025
72f8998
Update instructions (#8195)
rickhanlonii Dec 11, 2025
e44d3b7
Add additional DoS CVE (#8196)
rickhanlonii Dec 11, 2025
9527378
update nextjs instructions (#8197)
rickhanlonii Dec 12, 2025
1e74023
[Blog] Update safe Next.js versions (#8199)
mattcarrollcode Dec 12, 2025
2da4f7f
Update to Next.js 15.1.11 (#8200)
mattcarrollcode Dec 12, 2025
a1ddcf5
Add caveat to useId for cache keys (#8242)
rickhanlonii Jan 16, 2026
ed87618
Update DoS blog post with additional CVE (#8263)
rickhanlonii Jan 26, 2026
303e6b4
Init claude config (#8265)
rickhanlonii Jan 27, 2026
3938fbf
Update deps (#8268)
rickhanlonii Jan 28, 2026
dcc5deb
Add llms.txt (#8267)
gaearon Jan 28, 2026
61b1f51
Add sections to llms.txt and sitemap footer to *.md (#8270)
rickhanlonii Jan 28, 2026
d340c41
Remove feedback (#8271)
rickhanlonii Jan 28, 2026
a2a19ba
feat: Add Accept header content negotiation for markdown (#8272)
icyJoseph Jan 28, 2026
ec13a90
remove outdated note about streaming ssr (#8277)
hernan-yadiel Jan 29, 2026
24ec67e
fix: use beforeFiles (#8276)
icyJoseph Jan 30, 2026
29743d0
Revamp useOptimistic docs (#8264)
rickhanlonii Jan 30, 2026
4c52ab8
Update separating-events-from-effects.md (#8257)
wheresrhys Jan 30, 2026
38b52cf
More claude stuff (#8280)
rickhanlonii Jan 30, 2026
ff17a86
fix: correct typos and improve clarity in useOptimistic.md (#8283)
aurorascharff Feb 2, 2026
e05afa5
useEffectEvent revamp (#8279)
rickhanlonii Feb 4, 2026
bd87c39
Rephrase the rendering explanation paragraph (#8240)
BartoszKlonowski Feb 5, 2026
f653b03
Add .worktrees/ to .gitignore (#8297)
rickhanlonii Feb 10, 2026
46e040e
Fix date of CVE-2026-23864 (2025 => 2026) (#8302)
smikitky Feb 11, 2026
a19c98d
Fix confusion around Activity with text children (#8304)
eps1lon Feb 12, 2026
55a317d
Rewrite useActionState (#8284)
rickhanlonii Feb 15, 2026
a1cc2ab
Added missing prop to useActionState example (#8308)
JakeSaterlay Feb 17, 2026
c2aa350
Expand ViewTransition callback props reference documentation (#8306)
rickhanlonii Feb 23, 2026
68ff8c8
Add blog post: Launching the React Foundation (#8318)
mattcarrollcode Feb 24, 2026
e8ef063
Update logo credit link in uwu mode console log (#8315)
Cheesecake2960 Feb 25, 2026
dfa152b
[ViewTransition] Add docs for using with Activity (#8320)
rickhanlonii Feb 25, 2026
11e4ad5
Add /write command (#8327)
rickhanlonii Feb 27, 2026
427f24d
Add RSC Sandboxes (#8300)
rickhanlonii Feb 28, 2026
180364f
Add Copy Page button (#8341)
gaearon Mar 8, 2026
449d62c
Add ZurichJS Conference 2026 to community conferences
farisaziz12 Mar 8, 2026
7c90c6e
Update conferences: move past events (Sep 2025 – Feb 2026) to Past se…
aurorascharff Mar 8, 2026
40ea071
Fix copy button on Safari
gaearon Mar 9, 2026
1207ee3
fix: markdown rewrite excludes api/md paths (#8379)
icyJoseph Mar 31, 2026
e377252
Add no-trailing-spaces ESLint rule (#8356)
mattcarrollcode Apr 8, 2026
abe931a
fix: replace Imgur-hosted images with self-hosted assets (#8402)
travisbreaks Apr 9, 2026
028bcf6
merging all conflicts
react-translations-bot Apr 27, 2026
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Specify that Effects run on commit, not render (#8162)
  • Loading branch information
eps1lon authored Dec 11, 2025
commit cffb6a7b7d00fbe09df5b40d1731e1055bff0900
26 changes: 13 additions & 13 deletions src/content/reference/react/useEffect.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ function ChatRoom({ roomId }) {

#### Parameters {/*parameters*/}

* `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.
* `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.

* **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)
* **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)

#### Returns {/*returns*/}

Expand Down Expand Up @@ -107,14 +107,14 @@ You need to pass two arguments to `useEffect`:
**React calls your setup and cleanup functions whenever it's necessary, which may happen multiple times:**

1. Your <CodeStep step={1}>setup code</CodeStep> runs when your component is added to the page *(mounts)*.
2. After every re-render of your component where the <CodeStep step={3}>dependencies</CodeStep> have changed:
2. After every commit of your component where the <CodeStep step={3}>dependencies</CodeStep> have changed:
- First, your <CodeStep step={2}>cleanup code</CodeStep> runs with the old props and state.
- Then, your <CodeStep step={1}>setup code</CodeStep> runs with the new props and state.
3. Your <CodeStep step={2}>cleanup code</CodeStep> runs one final time after your component is removed from the page *(unmounts).*

**Let's illustrate this sequence for the example above.**

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.
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.

**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)

Expand Down Expand Up @@ -1145,7 +1145,7 @@ useEffect(() => {

#### Passing a dependency array {/*passing-a-dependency-array*/}

If you specify the dependencies, your Effect runs **after the initial render _and_ after re-renders with changed dependencies.**
If you specify the dependencies, your Effect runs **after the initial commit _and_ after commits with changed dependencies.**

```js {3}
useEffect(() => {
Expand Down Expand Up @@ -1242,7 +1242,7 @@ button { margin-left: 5px; }

#### Passing an empty dependency array {/*passing-an-empty-dependency-array*/}

If your Effect truly doesn't use any reactive values, it will only run **after the initial render.**
If your Effect truly doesn't use any reactive values, it will only run **after the initial commit.**

```js {3}
useEffect(() => {
Expand Down Expand Up @@ -1319,7 +1319,7 @@ export function createConnection(serverUrl, roomId) {

#### Passing no dependency array at all {/*passing-no-dependency-array-at-all*/}

If you pass no dependency array at all, your Effect runs **after every single render (and re-render)** of your component.
If you pass no dependency array at all, your Effect runs **after every single commit** of your component.

```js {3}
useEffect(() => {
Expand Down Expand Up @@ -1480,7 +1480,7 @@ Now that you're passing `c => c + 1` instead of `count + 1`, [your Effect no lon

### Removing unnecessary object dependencies {/*removing-unnecessary-object-dependencies*/}

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)
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)

```js {6-9,12,15}
const serverUrl = 'https://localhost:1234';
Expand All @@ -1497,7 +1497,7 @@ function ChatRoom({ roomId }) {
const connection = createConnection(options); // It's used inside the Effect
connection.connect();
return () => connection.disconnect();
}, [options]); // 🚩 As a result, these dependencies are always different on a re-render
}, [options]); // 🚩 As a result, these dependencies are always different on a commit
// ...
```

Expand Down Expand Up @@ -1583,7 +1583,7 @@ With this fix, typing into the input doesn't reconnect the chat. Unlike an objec

### Removing unnecessary function dependencies {/*removing-unnecessary-function-dependencies*/}

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)
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)

```js {4-9,12,16}
function ChatRoom({ roomId }) {
Expand All @@ -1601,11 +1601,11 @@ function ChatRoom({ roomId }) {
const connection = createConnection();
connection.connect();
return () => connection.disconnect();
}, [createOptions]); // 🚩 As a result, these dependencies are always different on a re-render
}, [createOptions]); // 🚩 As a result, these dependencies are always different on a commit
// ...
```

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.
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.

Avoid using a function created during rendering as a dependency. Instead, declare it inside the Effect:

Expand Down Expand Up @@ -1775,7 +1775,7 @@ First, check that you haven't forgotten to specify the dependency array:
```js {3}
useEffect(() => {
// ...
}); // 🚩 No dependency array: re-runs after every render!
}); // 🚩 No dependency array: re-runs after every commit!
```

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.
Expand Down
4 changes: 2 additions & 2 deletions src/content/reference/react/useLayoutEffect.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ function Tooltip() {

#### Parameters {/*parameters*/}

* `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.
* `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.

* **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.
* **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.

#### Returns {/*returns*/}

Expand Down