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
@@ -47,7 +47,7 @@ You can use Activity to hide part of your application:
47
47
48
48
When an Activity boundary becomes <CodeStepstep={1}>hidden</CodeStep>, React will visually hide its <CodeStepstep={2}>children</CodeStep> using the `display: "none"` CSS property. It will also destroy their Effects, cleaning up any active subscriptions.
49
49
50
-
While hidden, children still receive updates, albeit at a lower priority than the rest of the content.
50
+
While hidden, children still re-render in response to new props, albeit at a lower priority than the rest of the content.
51
51
52
52
When the boundary becomes <CodeStepstep={3}>visible</CodeStep> again, React will reveal the children with their previous state restored, and create their Effects.
53
53
@@ -889,35 +889,148 @@ Suspense-enabled data fetching without the use of an opinionated framework is no
889
889
890
890
---
891
891
892
-
### Deferring hydration of low-priority content {/*deferring-hydration-of-low-priority-content*/}
893
892
894
-
You can wrap part of your UI in a <CodeStepstep={3}>visible</CodeStep> Activity boundary to defer mounting it on the initial render:
893
+
### Reducing the time it takes to hydrate server-rendered content {/*reducing-the-time-it-takes-to-hydrate-server-rendered-content*/}
895
894
896
-
```jsx [[3,6,"\\"visible\\""]]
895
+
React includes an under-the-hood performance optimization called Selective Hydration. It works by hydrating your app's initial HTML _in chunks_, enabling some components to become interactive even if other components on the page haven't loaded their code or data yet.
896
+
897
+
Suspense boundaries participate in Selective Hydration, because they naturally divide your component tree into units that are independent from one another:
898
+
899
+
```jsx
897
900
functionPage() {
898
901
return (
899
902
<>
900
-
<Post />
901
-
902
-
<Activity mode="visible">
903
-
<Comments />
903
+
<MessageComposer />
904
+
905
+
<Suspense fallback="Loading chats...">
906
+
<Chats />
907
+
</Suspense>
908
+
</>
909
+
)
910
+
}
911
+
```
912
+
913
+
Here, `MessageComposer` can be fully hydrated during the initial render of the page, even before `Chats` is mounted and starts to fetch its data.
914
+
915
+
So by breaking up your component tree into discrete units, Suspense allows React to hydrate your app's server-rendered HTML in chunks, enabling parts of your app to become interactive as fast as possible.
Here, React must hydrate the entire page all at once. If `Home` or `Video` are slower to render, they could make the tab buttons feel unresponsive during hydration.
946
+
947
+
Adding Suspense around the active tab would solve this:
...but it would also change the UI, since the `Placeholder` fallback would be displayed on the initial render.
976
+
977
+
Instead, we can use Activity. Since Activity boundaries show and hide their children, they already naturally divide the component tree into independent units. And just like Suspense, this feature allows them to participate in Selective Hydration.
978
+
979
+
Let's update our example to use Activity boundaries around the active tab:
During hydration, React will leave the visible Activity boundary unmounted while hydrating the rest of the page, improving the performance of higher-priority content. Once the high-priority content has fetched its code and data, and been rendered to the page, React will move on to mount any remaining visible Activity boundaries.
1005
+
Now our initial server-rendered HTML looks the same as it did in the original version, but thanks to Activity, React can hydrate the tab buttons first, before it even mounts `Home` or `Video`.
911
1006
912
-
This feature is called Selective Hydration, and it's an under-the-hood optimization of React that's integrated with Suspense. You can read [an architectural overview](https://github.com/reactwg/react-18/discussions/37) and watch [a technical talk](https://www.youtube.com/watch?v=pj5N-Khihgc) to learn more.
1007
+
---
1008
+
1009
+
Thus, in addition to hiding and showing content, Activity boundaries help improve your app's performance during hydration by letting React know which parts of your page can become interactive in isolation.
1010
+
1011
+
And even if your page doesn't ever hide part of its content, you can still add always-visible Activity boundaries to improve hydration performance:
1012
+
1013
+
```jsx
1014
+
functionPage() {
1015
+
return (
1016
+
<>
1017
+
<Post />
1018
+
1019
+
<Activity>
1020
+
<Comments />
1021
+
</Activity>
1022
+
</>
1023
+
);
1024
+
}
1025
+
```
913
1026
914
1027
---
915
1028
916
1029
## Troubleshooting {/*troubleshooting*/}
917
1030
918
1031
### My hidden components have unwanted side effects {/*my-hidden-components-have-unwanted-side-effects*/}
919
1032
920
-
An Activity boundary hides its content by setting `display: none` on its children and cleaning up any of their [Effects](/reference/react/useEffect). So, most well-behaved React components that properly clean up their side effects will already be robust to being hidden by Activity.
1033
+
An Activity boundary hides its content by setting `display: none` on its children and cleaning up any of their Effects. So, most well-behaved React components that properly clean up their side effects will already be robust to being hidden by Activity.
921
1034
922
1035
But there _are_ some situations where a hidden component behaves differently than an unmounted one. Most notably, since a hidden component's DOM is not destroyed, any side effects from that DOM will persist, even after the component is hidden.
0 commit comments