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: beta/src/content/apis/react/useEffect.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1653,11 +1653,11 @@ function Page({ url, shoppingCart }) {
1653
1653
}
1654
1654
```
1655
1655
1656
-
**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. To do this, [declare an *Event function*](/learn/separating-events-from-effects#declaring-an-event-function) with the [`useEvent`](/apis/react/useEvent) Hook, and move the code that reads `shoppingCart` inside of it:
1656
+
**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`](/apis/react/useEffectEvent) Hook, and move the code that reads `shoppingCart` inside of it:
1657
1657
1658
1658
```js {2-4,7,8}
1659
1659
functionPage({ url, shoppingCart }) {
1660
-
constonVisit=useEvent(visitedUrl=> {
1660
+
constonVisit=useEffectEvent(visitedUrl=> {
1661
1661
logVisit(visitedUrl, shoppingCart.length)
1662
1662
});
1663
1663
@@ -1668,9 +1668,9 @@ function Page({ url, shoppingCart }) {
1668
1668
}
1669
1669
```
1670
1670
1671
-
**Event functions are not reactive and don't need to be specified as dependencies of your Effect.** This is what lets you put non-reactive code (where you can read the latest value of some props and state) inside of them. For example, by reading `shoppingCart` inside of `onVisit`, you ensure that `shoppingCart` won't re-run your Effect.
1671
+
**Effect Events are not reactive and must always be omitted from dependencies of your Effect.** This is what lets you put non-reactive code (where you can read the latest value of some props and state) inside of them. For example, by reading `shoppingCart` inside of `onVisit`, you ensure that `shoppingCart` won't re-run your Effect. In the future, the linter will support `useEffectEvent` and check that you omit Effect Events from dependencies.
1672
1672
1673
-
[Read more about how Event functions let you separate reactive and non-reactive code.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-event-functions)
1673
+
[Read more about how Effect Events let you separate reactive and non-reactive code.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events)
**This API is experimental and is not available in a stable version of React yet.**
8
+
9
+
See [`useEffectEvent` RFC](https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md) for details.
10
+
11
+
</Wip>
12
+
13
+
14
+
<Intro>
15
+
16
+
`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)
Copy file name to clipboardExpand all lines: beta/src/content/learn/removing-effect-dependencies.md
+26-26Lines changed: 26 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -350,7 +350,7 @@ Let's say that you wanted to run the Effect "only on mount". You've read that [e
350
350
351
351
This counter was supposed to increment every second by the amount configurable with the two buttons. However, since you "lied" to React that this Effect doesn't depend on anything, React forever keeps using the `onTick` function from the initial render. [During that render,](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) `count` was `0` and `increment` was `1`. This is why `onTick` from that render always calls `setCount(0+1)` every second, and you always see `1`. Bugs like this are harder to fix when they're spread across multiple components.
352
352
353
-
There's always a better solution than ignoring the linter! To fix this code, you need to add `onTick` to the dependency list. (To ensure the interval is only setup once, [make `onTick` an Event function.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-event-functions))
353
+
There's always a better solution than ignoring the linter! To fix this code, you need to add `onTick` to the dependency list. (To ensure the interval is only setup once, [make `onTick` an Effect Event.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events))
354
354
355
355
**We recommend to treat the dependency lint error as a compilation error. If you don't suppress it, you will never see bugs like this.** The rest of this page documents the alternatives for this and other cases.
356
356
@@ -655,16 +655,16 @@ function ChatRoom({ roomId }) {
655
655
656
656
The problem is that every time `isMuted` changes (for example, when the user presses the "Muted" toggle), the Effect will re-synchronize, and reconnect to the chat server. This is not the desired user experience! (In this example, even disabling the linter would not work--if you do that, `isMuted` would get "stuck" with its old value.)
657
657
658
-
To solve this problem, you need to extract the logic that shouldn't be reactive out of the Effect. You don't want this Effect to "react" to the changes in `isMuted`. [Move this non-reactive piece of logic into an Event function:](/learn/separating-events-from-effects#declaring-an-event-function)
658
+
To solve this problem, you need to extract the logic that shouldn't be reactive out of the Effect. You don't want this Effect to "react" to the changes in `isMuted`. [Move this non-reactive piece of logic into an Effect Event:](/learn/separating-events-from-effects#declaring-an-effect-event)
@@ -682,7 +682,7 @@ function ChatRoom({ roomId }) {
682
682
// ...
683
683
```
684
684
685
-
Event functions let you split an Effect into reactive parts (which should "react" to reactive values like `roomId` and their changes) and non-reactive parts (which only read their latest values, like `onMessage` reads `isMuted`). **Now that you read `isMuted` inside an Event function, it doesn't need to be a dependency of your Effect.** As a result, the chat won't re-connect when you toggle the "Muted" setting on and off, solving the original issue!
685
+
Effect Events let you split an Effect into reactive parts (which should "react" to reactive values like `roomId` and their changes) and non-reactive parts (which only read their latest values, like `onMessage` reads `isMuted`). **Now that you read `isMuted` inside an Effect Event, it doesn't need to be a dependency of your Effect.** As a result, the chat won't re-connect when you toggle the "Muted" setting on and off, solving the original issue!
686
686
687
687
#### Wrapping an event handler from the props {/*wrapping-an-event-handler-from-the-props*/}
688
688
@@ -714,13 +714,13 @@ Suppose that the parent component passes a *different* `onReceiveMessage` functi
714
714
/>
715
715
```
716
716
717
-
Since `onReceiveMessage` is a dependency of your Effect, it would cause the Effect to re-synchronize after every parent re-render. This would make it re-connect to the chat. To solve this, wrap the call in an Event function:
717
+
Since `onReceiveMessage` is a dependency of your Effect, it would cause the Effect to re-synchronize after every parent re-render. This would make it re-connect to the chat. To solve this, wrap the call in an Effect Event:
718
718
719
719
```js {4-6,12,15}
720
720
functionChatRoom({ roomId, onReceiveMessage }) {
721
721
const [messages, setMessages] =useState([]);
722
722
723
-
constonMessage=useEvent(receivedMessage=> {
723
+
constonMessage=useEffectEvent(receivedMessage=> {
724
724
onReceiveMessage(receivedMessage);
725
725
});
726
726
@@ -735,17 +735,17 @@ function ChatRoom({ roomId, onReceiveMessage }) {
735
735
// ...
736
736
```
737
737
738
-
Event functions aren't reactive, so you don't need to specify them as dependencies. As a result, the chat will no longer re-connect even if the parent component passes a function that's different on every re-render.
738
+
Effect Events aren't reactive, so you don't need to specify them as dependencies. As a result, the chat will no longer re-connect even if the parent component passes a function that's different on every re-render.
739
739
740
740
#### Separating reactive and non-reactive code {/*separating-reactive-and-non-reactive-code*/}
741
741
742
742
In this example, you want to log a visit every time `roomId` changes. You want to include the current `notificationCount` with every log, but you *don't* want a change to `notificationCount` to trigger a log event.
743
743
744
-
The solution is again to split out the non-reactive code into an Event function:
744
+
The solution is again to split out the non-reactive code into an Effect Event:
745
745
746
746
```js {2-4,7}
747
747
functionChat({ roomId, notificationCount }) {
748
-
constonVisit=useEvent(visitedRoomId=> {
748
+
constonVisit=useEffectEvent(visitedRoomId=> {
749
749
logVisit(visitedRoomId, notificationCount);
750
750
});
751
751
@@ -756,7 +756,7 @@ function Chat({ roomId, notificationCount }) {
756
756
}
757
757
```
758
758
759
-
You want your logic to be reactive with regards to `roomId`, so you read `roomId` inside of your Effect. However, you don't want a change to `notificationCount` to log an extra visit, so you read `notificationCount` inside of the Event function. [Learn more about reading the latest props and state from Effects using Event functions.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-event-functions)
759
+
You want your logic to be reactive with regards to `roomId`, so you read `roomId` inside of your Effect. However, you don't want a change to `notificationCount` to log an extra visit, so you read `notificationCount` inside of the Effect Event. [Learn more about reading the latest props and state from Effects using Effect Events.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events)
760
760
761
761
### Does some reactive value change unintentionally? {/*does-some-reactive-value-change-unintentionally*/}
762
762
@@ -1150,7 +1150,7 @@ function ChatRoom({ getOptions }) {
1150
1150
// ...
1151
1151
```
1152
1152
1153
-
This only works for [pure](/learn/keeping-components-pure) functions because they are safe to call during rendering. If your function is an event handler, but you don't want its changes to re-synchronize your Effect, [wrap it into an Event function instead.](#do-you-want-to-read-a-value-without-reacting-to-its-changes)
1153
+
This only works for [pure](/learn/keeping-components-pure) functions because they are safe to call during rendering. If your function is an event handler, but you don't want its changes to re-synchronize your Effect, [wrap it into an Effect Event instead.](#do-you-want-to-read-a-value-without-reacting-to-its-changes)
1154
1154
1155
1155
<Recap>
1156
1156
@@ -1161,7 +1161,7 @@ This only works for [pure](/learn/keeping-components-pure) functions because the
1161
1161
- If the code in your Effect should run in response to a specific interaction, move that code to an event handler.
1162
1162
- If different parts of your Effect should re-run for different reasons, split it into several Effects.
1163
1163
- If you want to update some state based on the previous state, pass an updater function.
1164
-
- If you want to read the latest value without "reacting" it, extract an Event function from your Effect.
1164
+
- If you want to read the latest value without "reacting" it, extract an Effect Event from your Effect.
1165
1165
- In JavaScript, objects and functions are considered different if they were created at different times.
1166
1166
- Try to avoid object and function dependencies. Move them outside the component or inside the Effect.
1167
1167
@@ -1273,7 +1273,7 @@ Is there a line of code inside the Effect that should not be reactive? How can y
@@ -1378,7 +1378,7 @@ html, body { min-height: 300px; }
1378
1378
1379
1379
<Solution>
1380
1380
1381
-
Your Effect needs to read the latest value of `duration`, but you don't want it to "react" to changes in `duration`. You use `duration` to start the animation, but starting animation isn't reactive. Extract the non-reactive line of code into an Event function, and call that function from your Effect.
1381
+
Your Effect needs to read the latest value of `duration`, but you don't want it to "react" to changes in `duration`. You use `duration` to start the animation, but starting animation isn't reactive. Extract the non-reactive line of code into an Effect Event, and call that function from your Effect.
1382
1382
1383
1383
<Sandpack>
1384
1384
@@ -1401,12 +1401,12 @@ Your Effect needs to read the latest value of `duration`, but you don't want it
@@ -2031,19 +2031,19 @@ There's more than one correct way to solve this, but the here is one possible so
2031
2031
2032
2032
In the original example, toggling the theme caused different `onMessage` and `createConnection` functions to be created and passed down. Since the Effect depended on these functions, the chat would re-connect every time you toggle the theme.
2033
2033
2034
-
To fix the problem with `onMessage`, you needed to wrap it into an Event function:
2034
+
To fix the problem with `onMessage`, you needed to wrap it into an Effect Event:
Unlike the `onMessage` prop, the `onReceiveMessage`Event function is not reactive. This is why it doesn't need to be a dependency of your Effect. As a result, changes to `onMessage` won't cause the chat to re-connect.
2046
+
Unlike the `onMessage` prop, the `onReceiveMessage`Effect Event is not reactive. This is why it doesn't need to be a dependency of your Effect. As a result, changes to `onMessage` won't cause the chat to re-connect.
2047
2047
2048
2048
You can't do the same with `createConnection` because it *should* be reactive. You *want* the Effect to re-trigger if the user switches between an encrypted and an unencryption connection, or if the user switches the current room. However, because `createConnection` is a function, you can't check whether the information it reads has *actually* changed or not. To solve this, instead of passing `createConnection` down from the `App` component, pass the raw `roomId` and `isEncrypted` values:
0 commit comments