diff --git a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md
index c7f74009165..5d2c59b7615 100644
--- a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md
+++ b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md
@@ -14303,7 +14303,7 @@ useEffect(() => {
}); // compiler inserted dependencies.
```
-With this code, the React Compiler can infer the dependencies for you and insert them automatically so you don't need to see or write them. With features like [the IDE extension](#compiler-ide-extension) and [`useEffectEvent`](/reference/react/experimental_useEffectEvent), we can provide a CodeLens to show you what the Compiler inserted for times you need to debug, or to optimize by removing a dependency. This helps reinforce the correct mental model for writing Effects, which can run at any time to synchronize your component or hook's state with something else.
+With this code, the React Compiler can infer the dependencies for you and insert them automatically so you don't need to see or write them. With features like [the IDE extension](#compiler-ide-extension) and [`useEffectEvent`](/reference/react/useEffectEvent), we can provide a CodeLens to show you what the Compiler inserted for times you need to debug, or to optimize by removing a dependency. This helps reinforce the correct mental model for writing Effects, which can run at any time to synchronize your component or hook's state with something else.
Our hope is that automatically inserting dependencies is not only easier to write, but that it also makes them easier to understand by forcing you to think in terms of what the Effect does, and not in component lifecycles.
diff --git a/src/content/learn/escape-hatches.md b/src/content/learn/escape-hatches.md
index 0b2d595b2bd..e6b050e0e96 100644
--- a/src/content/learn/escape-hatches.md
+++ b/src/content/learn/escape-hatches.md
@@ -455,8 +455,8 @@ This is not ideal. You want to re-connect to the chat only if the `roomId` has c
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -471,7 +471,7 @@ This is not ideal. You want to re-connect to the chat only if the `roomId` has c
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import { createConnection, sendMessage } from './chat.js';
import { showNotification } from './notifications.js';
diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md
index 7ab6dbc1f42..fb98a0cd148 100644
--- a/src/content/learn/removing-effect-dependencies.md
+++ b/src/content/learn/removing-effect-dependencies.md
@@ -609,11 +609,13 @@ function ChatRoom({ roomId }) {
### Do you want to read a value without "reacting" to its changes? {/*do-you-want-to-read-a-value-without-reacting-to-its-changes*/}
-
+
-This section describes an **experimental API that has not yet been released** in a stable version of React.
+**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.**
-
+[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
+
+
Suppose that you want to play a sound when the user receives a new message unless `isMuted` is `true`:
@@ -1262,8 +1264,8 @@ Is there a line of code inside the Effect that should not be reactive? How can y
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1277,7 +1279,7 @@ Is there a line of code inside the Effect that should not be reactive? How can y
```js
import { useState, useEffect, useRef } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import { FadeInAnimation } from './animation.js';
function Welcome({ duration }) {
@@ -1389,8 +1391,8 @@ Your Effect needs to read the latest value of `duration`, but you don't want it
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1405,7 +1407,7 @@ Your Effect needs to read the latest value of `duration`, but you don't want it
```js
import { useState, useEffect, useRef } from 'react';
import { FadeInAnimation } from './animation.js';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
function Welcome({ duration }) {
const ref = useRef(null);
@@ -1825,8 +1827,8 @@ Another of these functions only exists to pass some state to an imported API met
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1907,7 +1909,7 @@ export default function App() {
```js src/ChatRoom.js active
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export default function ChatRoom({ roomId, createConnection, onMessage }) {
useEffect(() => {
@@ -2120,8 +2122,8 @@ As a result, the chat re-connects only when something meaningful (`roomId` or `i
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -2189,7 +2191,7 @@ export default function App() {
```js src/ChatRoom.js active
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import {
createEncryptedConnection,
createUnencryptedConnection,
diff --git a/src/content/learn/reusing-logic-with-custom-hooks.md b/src/content/learn/reusing-logic-with-custom-hooks.md
index de68dd190aa..2038e59e16c 100644
--- a/src/content/learn/reusing-logic-with-custom-hooks.md
+++ b/src/content/learn/reusing-logic-with-custom-hooks.md
@@ -837,11 +837,13 @@ Every time your `ChatRoom` component re-renders, it passes the latest `roomId` a
### Passing event handlers to custom Hooks {/*passing-event-handlers-to-custom-hooks*/}
-
+
-This section describes an **experimental API that has not yet been released** in a stable version of React.
+**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.**
-
+[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
+
+
As you start using `useChatRoom` in more components, you might want to let components customize its behavior. For example, currently, the logic for what to do when a message arrives is hardcoded inside the Hook:
@@ -985,7 +987,7 @@ export default function ChatRoom({ roomId }) {
```js src/useChatRoom.js
import { useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import { createConnection } from './chat.js';
export function useChatRoom({ serverUrl, roomId, onReceiveMessage }) {
@@ -1070,8 +1072,8 @@ export function showNotification(message, theme = 'dark') {
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1666,7 +1668,7 @@ export default function App() {
```js src/useFadeIn.js active
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export function useFadeIn(ref, duration) {
const [isRunning, setIsRunning] = useState(true);
@@ -1719,8 +1721,8 @@ html, body { min-height: 300px; }
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -2208,8 +2210,8 @@ It looks like your `useInterval` Hook accepts an event listener as an argument.
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -2252,7 +2254,7 @@ export function useCounter(delay) {
```js src/useInterval.js
import { useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export function useInterval(onTick, delay) {
useEffect(() => {
@@ -2279,8 +2281,8 @@ With this change, both intervals work as expected and don't interfere with each
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -2324,7 +2326,7 @@ export function useCounter(delay) {
```js src/useInterval.js active
import { useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export function useInterval(callback, delay) {
const onTick = useEffectEvent(callback);
diff --git a/src/content/learn/separating-events-from-effects.md b/src/content/learn/separating-events-from-effects.md
index fd603c39556..2a19e0f13a1 100644
--- a/src/content/learn/separating-events-from-effects.md
+++ b/src/content/learn/separating-events-from-effects.md
@@ -400,13 +400,15 @@ You need a way to separate this non-reactive logic from the reactive Effect arou
### Declaring an Effect Event {/*declaring-an-effect-event*/}
-
+
-This section describes an **experimental API that has not yet been released** in a stable version of React.
+**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.**
-
+[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
-Use a special Hook called [`useEffectEvent`](/reference/react/experimental_useEffectEvent) to extract this non-reactive logic out of your Effect:
+
+
+Use a special Hook called [`useEffectEvent`](/reference/react/useEffectEvent) to extract this non-reactive logic out of your Effect:
```js {1,4-6}
import { useEffect, useEffectEvent } from 'react';
@@ -448,8 +450,8 @@ Verify that the new behavior works as you would expect:
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -464,7 +466,7 @@ Verify that the new behavior works as you would expect:
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import { createConnection, sendMessage } from './chat.js';
import { showNotification } from './notifications.js';
@@ -578,11 +580,13 @@ You can think of Effect Events as being very similar to event handlers. The main
### Reading latest props and state with Effect Events {/*reading-latest-props-and-state-with-effect-events*/}
-
+
+
+**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.**
-This section describes an **experimental API that has not yet been released** in a stable version of React.
+[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
-
+
Effect Events let you fix many patterns where you might be tempted to suppress the dependency linter.
@@ -803,8 +807,8 @@ With `useEffectEvent`, there is no need to "lie" to the linter, and the code wor
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -818,7 +822,7 @@ With `useEffectEvent`, there is no need to "lie" to the linter, and the code wor
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export default function App() {
const [position, setPosition] = useState({ x: 0, y: 0 });
@@ -878,11 +882,13 @@ Read [Removing Effect Dependencies](/learn/removing-effect-dependencies) for oth
### Limitations of Effect Events {/*limitations-of-effect-events*/}
-
+
+
+**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.**
-This section describes an **experimental API that has not yet been released** in a stable version of React.
+[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
-
+
Effect Events are very limited in how you can use them:
@@ -976,8 +982,8 @@ To fix this code, it's enough to follow the rules.
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1046,8 +1052,8 @@ If you remove the suppression comment, React will tell you that this Effect's co
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1124,8 +1130,8 @@ It seems like the Effect which sets up the timer "reacts" to the `increment` val
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1139,7 +1145,7 @@ It seems like the Effect which sets up the timer "reacts" to the `increment` val
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export default function Timer() {
const [count, setCount] = useState(0);
@@ -1193,8 +1199,8 @@ To solve the issue, extract an `onTick` Effect Event from the Effect:
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1208,7 +1214,7 @@ To solve the issue, extract an `onTick` Effect Event from the Effect:
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export default function Timer() {
const [count, setCount] = useState(0);
@@ -1275,8 +1281,8 @@ Code inside Effect Events is not reactive. Are there cases in which you would _w
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1290,7 +1296,7 @@ Code inside Effect Events is not reactive. Are there cases in which you would _w
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export default function Timer() {
const [count, setCount] = useState(0);
@@ -1362,8 +1368,8 @@ The problem with the above example is that it extracted an Effect Event called `
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1377,7 +1383,7 @@ The problem with the above example is that it extracted an Effect Event called `
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
export default function Timer() {
const [count, setCount] = useState(0);
@@ -1458,8 +1464,8 @@ Your Effect knows which room it connected to. Is there any information that you
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1474,7 +1480,7 @@ Your Effect knows which room it connected to. Is there any information that you
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import { createConnection, sendMessage } from './chat.js';
import { showNotification } from './notifications.js';
@@ -1599,8 +1605,8 @@ To fix the issue, instead of reading the *latest* `roomId` inside the Effect Eve
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1615,7 +1621,7 @@ To fix the issue, instead of reading the *latest* `roomId` inside the Effect Eve
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import { createConnection, sendMessage } from './chat.js';
import { showNotification } from './notifications.js';
@@ -1736,8 +1742,8 @@ To solve the additional challenge, save the notification timeout ID and clear it
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1752,7 +1758,7 @@ To solve the additional challenge, save the notification timeout ID and clear it
```js
import { useState, useEffect } from 'react';
-import { experimental_useEffectEvent as useEffectEvent } from 'react';
+import { useEffectEvent } from 'react';
import { createConnection, sendMessage } from './chat.js';
import { showNotification } from './notifications.js';
diff --git a/src/content/reference/react/experimental_useEffectEvent.md b/src/content/reference/react/experimental_useEffectEvent.md
deleted file mode 100644
index 954cf6587d0..00000000000
--- a/src/content/reference/react/experimental_useEffectEvent.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-title: experimental_useEffectEvent
-version: experimental
----
-
-
-
-**This API is experimental and is not available in a stable version of React yet.**
-
-You can try it by upgrading React packages to the most recent experimental version:
-
-- `react@experimental`
-- `react-dom@experimental`
-- `eslint-plugin-react-hooks@experimental`
-
-Experimental versions of React may contain bugs. Don't use them in production.
-
-
-
-
-
-
-`useEffectEvent` is a React Hook that lets you extract non-reactive logic into an [Effect Event.](/learn/separating-events-from-effects#declaring-an-effect-event)
-
-```js
-const onSomething = useEffectEvent(callback)
-```
-
-
-
-
diff --git a/src/content/reference/react/useEffect.md b/src/content/reference/react/useEffect.md
index a250bb15a24..7ead26dffbd 100644
--- a/src/content/reference/react/useEffect.md
+++ b/src/content/reference/react/useEffect.md
@@ -1691,11 +1691,13 @@ Now that you define the `createOptions` function inside the Effect, the Effect i
### Reading the latest props and state from an Effect {/*reading-the-latest-props-and-state-from-an-effect*/}
-
+
-This section describes an **experimental API that has not yet been released** in a stable version of React.
+**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.**
-
+[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
+
+
By default, when you read a reactive value from an Effect, you have to add it as a dependency. This ensures that your Effect "reacts" to every change of that value. For most dependencies, that's the behavior you want.
@@ -1710,7 +1712,7 @@ function Page({ url, shoppingCart }) {
}
```
-**What if you want to log a new page visit after every `url` change, but *not* if only the `shoppingCart` changes?** You can't exclude `shoppingCart` from dependencies without breaking the [reactivity rules.](#specifying-reactive-dependencies) However, you can express that you *don't want* a piece of code to "react" to changes even though it is called from inside an Effect. [Declare an *Effect Event*](/learn/separating-events-from-effects#declaring-an-effect-event) with the [`useEffectEvent`](/reference/react/experimental_useEffectEvent) Hook, and move the code reading `shoppingCart` inside of it:
+ **What if you want to log a new page visit after every `url` change, but *not* if only the `shoppingCart` changes?** You can't exclude `shoppingCart` from dependencies without breaking the [reactivity rules.](#specifying-reactive-dependencies) However, you can express that you *don't want* a piece of code to "react" to changes even though it is called from inside an Effect. [Declare an *Effect Event*](/learn/separating-events-from-effects#declaring-an-effect-event) with the [`useEffectEvent`](/reference/react/useEffectEvent) Hook, and move the code reading `shoppingCart` inside of it:
```js {2-4,7,8}
function Page({ url, shoppingCart }) {
diff --git a/src/content/reference/react/useEffectEvent.md b/src/content/reference/react/useEffectEvent.md
new file mode 100644
index 00000000000..8792f7ffb4a
--- /dev/null
+++ b/src/content/reference/react/useEffectEvent.md
@@ -0,0 +1,102 @@
+---
+title: useEffectEvent
+version: canary
+---
+
+
+
+
+**The `useEffectEvent` API is currently only available in React’s Canary and Experimental channels.**
+
+[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
+
+
+
+
+
+`useEffectEvent` is a React Hook that lets you extract non-reactive logic from your Effects into a reusable function called an [Effect Event](/learn/separating-events-from-effects#declaring-an-effect-event).
+
+```js
+const onSomething = useEffectEvent(callback)
+```
+
+
+
+
+
+## Reference {/*reference*/}
+
+### `useEffectEvent(callback)` {/*useeffectevent*/}
+
+Call `useEffectEvent` at the top level of your component to declare an Effect Event. Effect Events are functions you can call inside Effects, such as `useEffect`:
+
+```js {4-6,11}
+import { useEffectEvent, useEffect } from 'react';
+
+function ChatRoom({ roomId, theme }) {
+ const onConnected = useEffectEvent(() => {
+ showNotification('Connected!', theme);
+ });
+
+ useEffect(() => {
+ const connection = createConnection(serverUrl, roomId);
+ connection.on('connected', () => {
+ onConnected();
+ });
+ connection.connect();
+ return () => connection.disconnect();
+ }, [roomId]);
+
+ // ...
+}
+```
+
+[See more examples below.](#usage)
+
+#### Parameters {/*parameters*/}
+
+- `callback`: A function containing the logic for your Effect Event. When you define an Effect Event with `useEffectEvent`, the `callback` always accesses the latest values from props and state when it is invoked. This helps avoid issues with stale closures.
+
+#### Returns {/*returns*/}
+
+Returns an Effect Event function. You can call this function inside `useEffect`, `useLayoutEffect`, or `useInsertionEffect`.
+
+#### Caveats {/*caveats*/}
+
+- **Only call inside Effects:** Effect Events should only be called within Effects. Define them just before the Effect that uses them. Do not pass them to other components or hooks.
+- **Not a dependency shortcut:** Do not use `useEffectEvent` to avoid specifying dependencies in your Effect's dependency array. This can hide bugs and make your code harder to understand. Prefer explicit dependencies or use refs to compare previous values if needed.
+- **Use for non-reactive logic:** Only use `useEffectEvent` to extract logic that does not depend on changing values.
+
+___
+
+## Usage {/*usage*/}
+
+### Reading the latest props and state {/*reading-the-latest-props-and-state*/}
+
+Typically, when you access a reactive value inside an Effect, you must include it in the dependency array. This makes sure your Effect runs again whenever that value changes, which is usually the desired behavior.
+
+But in some cases, you may want to read the most recent props or state inside an Effect without causing the Effect to re-run when those values change.
+
+To [read the latest props or state](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events) in your Effect, without making those values reactive, include them in an Effect Event.
+
+```js {7-9,12}
+import { useEffect, useContext, useEffectEvent } from 'react';
+
+function Page({ url }) {
+ const { items } = useContext(ShoppingCartContext);
+ const numberOfItems = items.length;
+
+ const onNavigate = useEffectEvent((visitedUrl) => {
+ logVisit(visitedUrl, numberOfItems);
+ });
+
+ useEffect(() => {
+ onNavigate(url);
+ }, [url]);
+
+ // ...
+}
+```
+
+You can pass reactive values like `url` as arguments to the Effect Event. This lets you access the latest values without making your Effect re-run for every change.
+
diff --git a/src/sidebarReference.json b/src/sidebarReference.json
index 8823effb2e1..67935b45978 100644
--- a/src/sidebarReference.json
+++ b/src/sidebarReference.json
@@ -38,6 +38,11 @@
"title": "useEffect",
"path": "/reference/react/useEffect"
},
+ {
+ "title": "useEffectEvent",
+ "path": "/reference/react/useEffectEvent",
+ "version": "canary"
+ },
{
"title": "useId",
"path": "/reference/react/useId"
diff --git a/vercel.json b/vercel.json
index 1a55e20634e..70ddefbe8b9 100644
--- a/vercel.json
+++ b/vercel.json
@@ -248,6 +248,11 @@
"source": "/feed.xml",
"destination": "/rss.xml",
"permanent": true
+ },
+ {
+ "source": "/reference/react/experimental_useEffectEvent",
+ "destination": "/reference/react/useEffectEvent",
+ "permanent": true
}
],
"headers": [