Skip to content

Commit 63e6479

Browse files
committed
wip
1 parent 54d4a5e commit 63e6479

File tree

3 files changed

+33
-36
lines changed

3 files changed

+33
-36
lines changed

src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ In React Labs posts, we write about projects in active research and development.
2020

2121
React Conf 2025 is scheduled for October 7–8 in Henderson, Nevada!
2222

23-
We're looking for speakers to help us create talks about the features covered in this post. If you're interested in speaking at ReactConf, [please apply here](https://forms.reform.app/react-conf/call-for-speakers/piaae1?ga4_visitor_id=c3e8f3ce-2004-47a5-b801-f6b308280acd) (no talk proposal required).
23+
We're looking for speakers to help us create talks about the features covered in this post. If you're interested in speaking at ReactConf, [please apply here](https://forms.reform.app/react-conf/call-for-speakers/) (no talk proposal required).
2424

2525
For more info on tickets, free streaming, sponsoring, and more, see [the React Conf website](https://conf.react.dev).
2626

@@ -59,7 +59,7 @@ Read on to learn how to use these features in your app, or check out the newly p
5959

6060
## View Transitions {/*view-transitions*/}
6161

62-
React View Transitions are a new experimental feature that makes it easier to add animations to UI transitions in your app. Under-the-hood, these animations APIs use the new [`startViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) API available in most modern browsers.
62+
React View Transitions are a new experimental feature that makes it easier to add animations to UI transitions in your app. Under-the-hood, these animations use the new [`startViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) API available in most modern browsers.
6363

6464
To opt-in to animating an element, wrap it in the new `<ViewTransition>` component:
6565

@@ -4905,7 +4905,7 @@ With transition types, you can provide custom animations via props to `<ViewTran
49054905
</ViewTransition>
49064906
```
49074907

4908-
Here we pass a `share` prop to define how to animate based on the transiton type. When the share transition activates from `nav-forward`, the view transition class `slide-forward` is applied. When it's from `nav-back`, the `slide-back` animation is activated. Let's define these animations in CSS:
4908+
Here we pass a `share` prop to define how to animate based on the transition type. When the share transition activates from `nav-forward`, the view transition class `slide-forward` is applied. When it's from `nav-back`, the `slide-back` animation is activated. Let's define these animations in CSS:
49094909

49104910
```css
49114911
::view-transition-old(.slide-forward) {
@@ -10143,9 +10143,9 @@ We're now ready to share the API and how it works, so you can start testing it i
1014310143
</Activity>
1014410144
```
1014510145

10146-
When an Activity is <CodeStep step={1}>visible</CodeStep> it's rendered as normal. When an Activity is <CodeStep step={2}>hidden</CodeStep> it is unmounted, but will save it's state and continue to render at a lower priority than anything visible on screen.
10146+
When an Activity is <CodeStep step={1}>visible</CodeStep> it's rendered as normal. When an Activity is <CodeStep step={2}>hidden</CodeStep> it is unmounted, but will save its state and continue to render at a lower priority than anything visible on screen.
1014710147

10148-
You can use `Activity` save state for parts of the UI the user isn't using, or pre-render parts that a user is likely to use next.
10148+
You can use `Activity` to save state for parts of the UI the user isn't using, or pre-render parts that a user is likely to use next.
1014910149

1015010150
Let's look at some examples improving the View Transition examples above.
1015110151

@@ -10176,7 +10176,7 @@ function App() {
1017610176
}
1017710177
```
1017810178

10179-
However, this means if the user goes back to the old page, all of the previous state is lost. For example, if the `<Home />` page has an `<input>` field, when the user leaves the page the `<input`> is unmouted, and all of the text they had typed is lost.
10179+
However, this means if the user goes back to the old page, all of the previous state is lost. For example, if the `<Home />` page has an `<input>` field, when the user leaves the page the `<input`> is unmounted, and all of the text they had typed is lost.
1018010180

1018110181
Activity allows you to keep the state around as the user changes pages, so when they come back they can resume where they left off. This is done by wrapping part of the tree in `<Activity>` and toggling the `mode`:
1018210182

@@ -11516,7 +11516,7 @@ root.render(
1151611516

1151711517
Sometimes, you may want to prepare the next part of the UI a user is likely to use ahead of time, so it's ready by the time they are ready to use it. This is especially useful if the next route needs to suspend on data it needs to render, because you can help ensure the data is already fetched before the user navigates.
1151811518

11519-
For example, our app currently needs to suspend to load the data for each video when you select one. We can improve this by rendering all of the pages is a hidden `<Activity>` until the user navigates:
11519+
For example, our app currently needs to suspend to load the data for each video when you select one. We can improve this by rendering all of the pages in a hidden `<Activity>` until the user navigates:
1152011520

1152111521
```js {2,5,8}
1152211522
<ViewTransition>
@@ -11560,16 +11560,13 @@ export default function App() {
1156011560
}
1156111561
```
1156211562

11563-
```js src/Details.js hidden
11564-
import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react";
11565-
import { fetchVideo, fetchVideoDetails } from "./data";
11566-
import { Thumbnail, VideoControls } from "./Videos";
11567-
import { useRouter } from "./router";
11568-
import Layout from "./Layout";
11569-
import { ChevronLeft } from "./Icons";
11563+
```js src/Details.js
11564+
import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
1157011565

1157111566
function VideoDetails({id}) {
11572-
// Animate from Suspense fallback to content
11567+
// Animate from Suspense fallback to content.
11568+
// If this is pre-rendered then the fallback
11569+
// won't need to show.
1157311570
return (
1157411571
<Suspense
1157511572
fallback={
@@ -12884,7 +12881,7 @@ Earlier this week [we shared](/blog/2025/04/21/react-compiler-rc) the React Comp
1288412881

1288512882
We've also begun exploring ways to use the React Compiler to provide information that can improve understanding and debugging your code. One idea we've started exploring is a new experimental LSP-based React IDE extension powered by React Compiler, similar to the extension used in [Lauren Tan's React Conf talk](https://conf2024.react.dev/talks/5).
1288612883

12887-
Our idea is that we can use the compiler's static analysis to provide more information, suggestions, and optimization opportunities directly in your IDE. For example, we can provide diagnostics for code breaking the Rules of React, hovers to show if components and hooks were optimized by the compiler, or a CodeLens to see [automatically inserted Effect dependencies](/#automatic-effect-dependencies).
12884+
Our idea is that we can use the compiler's static analysis to provide more information, suggestions, and optimization opportunities directly in your IDE. For example, we can provide diagnostics for code breaking the Rules of React, hovers to show if components and hooks were optimized by the compiler, or a CodeLens to see [automatically inserted Effect dependencies](#automatic-effect-dependencies).
1288812885

1288912886
The IDE extension is still an early exploration, but we'll share our progress in future updates.
1289012887

@@ -12902,11 +12899,11 @@ Since their release, hooks have been successful at *sharing code between compone
1290212899

1290312900
### Effects can be hard {/*effects-can-be-hard*/}
1290412901

12905-
Unfortunately, some hooks are still hard to think in terms of function instead of lifecycles. Effects specifically are still hard to understand and is the most common pain point we hear from developers. Last year, we spent a significant amount of time researching how effects were used, and how those use cases could be simplified and easier to understand.
12902+
Unfortunately, some hooks are still hard to think in terms of function instead of lifecycles. Effects specifically are still hard to understand and is the most common pain point we hear from developers. Last year, we spent a significant amount of time researching how Effects were used, and how those use cases could be simplified and easier to understand.
1290612903

12907-
We found that often, the confusion is from using an Effect when you don't need to. The [You Probably Don't Need an Effect guide](/TODO), covers many cases for when Effects are not the right solution. However, even when an Effect is the right fit for a problem, Effects can still be harder to understand than class component lifecyles.
12904+
We found that often, the confusion is from using an Effect when you don't need to. The [You Might Not Need an Effect](/learn/you-might-not-need-an-effect) guide, covers many cases for when Effects are not the right solution. However, even when an Effect is the right fit for a problem, Effects can still be harder to understand than class component lifecyles.
1290812905

12909-
We believe one of the reasons for confusion is the dependency array, which allows developers to think of effects from the _components_ perspective (like a lifecycle), instead of the _effects_ point of view (what the effect does).
12906+
We believe one of the reasons for confusion is that developers to think of Effects from the _components_ perspective (like a lifecycle), instead of the _Effects_ point of view (what the Effect does).
1291012907

1291112908
Let's look at an example [from the docs](/learn/lifecycle-of-reactive-effects#thinking-from-the-effects-perspective):
1291212909

@@ -12926,7 +12923,7 @@ Many users would read this code as "on mount, connect to the roomId. whenever `r
1292612923

1292712924
### Effects without dependencies {/*effects-without-dependencies*/}
1292812925

12929-
Instaed, it's better to think from the Effect's perspective. The effect doesn't know about about the component lifecycles. It only describes how to start synchronization and how to stop it. When users think of Effects in this way, their Effects tend to be easier to write, and more resilient to being started and stopped as many times as it’s needed.
12926+
Instead, it's better to think from the Effect's perspective. The effect doesn't know about the component lifecycles. It only describes how to start synchronization and how to stop it. When users think of Effects in this way, their Effects tend to be easier to write, and more resilient to being started and stopped as many times as it’s needed.
1293012927

1293112928
We spent some time researching why Effects are thought of from the component perspective, and we think one of the resons is the dependency array. Since you have to write it, it's right there and in your face reminding you of what you're "reacting" to and baiting you into the mental model of 'do this when these values change'.
1293212929

@@ -12942,7 +12939,7 @@ useEffect(() => {
1294212939
}); // compiler inserted dependencies.
1294312940
```
1294412941

12945-
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 exension and `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
12942+
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 exension and `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.
1294612943

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

@@ -12990,4 +12987,4 @@ This research is still early. We'll share more, and what the new APIs will look
1299012987

1299112988
---
1299212989

12993-
_TODO: Thanks to [Dan Abramov](https://bsky.app/profile/danabra.mov), [Lauren Tan](https://bsky.app/profile/no.lol), [Matt Carroll](https://twitter.com/mattcarrollcode), [Jack Pope](https://jackpope.me), [Jason Bonta](https://threads.net/someextent), [Jordan Brown](https://github.com/jbrown215), [Jordan Eldredge](https://bsky.app/profile/capt.dev), and [Mofei Zhang](https://threads.net/z_mofei) for reviewing this post.
12990+
_TODO: Thanks to [Aurora Scharff](https://bsky.app/profile/aurorascharff.no), [Dan Abramov](https://bsky.app/profile/danabra.mov), [Lauren Tan](https://bsky.app/profile/no.lol), [Luna Wei](https://github.com/lunaleaps), [Matt Carroll](https://twitter.com/mattcarrollcode), [Jack Pope](https://jackpope.me), [Jason Bonta](https://threads.net/someextent), [Jordan Brown](https://github.com/jbrown215), [Jordan Eldredge](https://bsky.app/profile/capt.dev), [Mofei Zhang](https://threads.net/z_mofei), [Sebastien Lorber](https://bsky.app/profile/sebastienlorber.com), and [Sebastian Markbåge](https://bsky.app/profile/sebmarkbage.calyptus.eu) for reviewing this post.

src/content/reference/react/Activity.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,17 @@ Under the hood...
8181

8282
You can pre-render part of the UI using `<Activity mode="hidden">`:
8383

84-
```js [[1, 1, "Activity"], [1, 3, "Activity"], [2, 1, "mode"], [3, 1, "visible"], [4, 1, "hidden"]]
84+
```js
8585
<Activity mode={tab === "posts" ? "visible" : "hidden"}>
8686
<PostsTab />
8787
</Activity>
8888
```
8989

90-
When an <CodeStep step={1}>Activity</CodeStep> is rendered with <CodeStep step={2}>mode</CodeStep> "hidden", the `children` are not visible on the page, but are rendered at lower prioirty than the visible content on the page.
90+
When an Activity is rendered with `mode` "hidden"`, the `children` are not visible on the page, but are rendered at lower prioirty than the visible content on the page.
9191

92-
When the <CodeStep step={2}>mode</CodeStep> later switches to <CodeStep step={4}>visible</CodeStep>, the pre-rendered children will mount and become visible. This can be used to prepare parts of the UI the user is likely to interact with next to reduce loading times.
92+
When the `mode` later switches to "visible", the pre-rendered children will mount and become visible. This can be used to prepare parts of the UI the user is likely to interact with next to reduce loading times.
9393

94-
In the follow example from [`useTransition`](/reference/react/useTransition#preventing-unwanted-loading-indicators), the `PostsTab` component fetches some data using `use`. When you click the “Posts” tab, the `PostsTab` component suspends, causing the button loading state to appear:
94+
In the following example from [`useTransition`](/reference/react/useTransition#preventing-unwanted-loading-indicators), the `PostsTab` component fetches some data using `use`. When you click the “Posts” tab, the `PostsTab` component suspends, causing the button loading state to appear:
9595

9696
<Sandpack>
9797

@@ -481,17 +481,17 @@ b { display: inline-block; margin-right: 10px; }
481481

482482
You can keep state for parts of the UI by switching `<Activity>` from "visible" to "hidden":
483483

484-
```js [[1, 1, "Activity"], [1, 3, "Activity"], [2, 1, "mode"], [3, 1, "visible"], [4, 1, "hidden"]]
484+
```js
485485
<Activity mode={tab === "posts" ? "visible" : "hidden"}>
486486
<PostsTab />
487487
</Activity>
488488
```
489489

490-
When an <CodeStep step={1}>Activity</CodeStep> is switches from <CodeStep step={2}>mode</CodeStep> <CodeStep step={3}>visible</CodeStep> to <CodeStep step={4}>hidden</CodeStep>, the `children` will become hidden on the page, and unmount by destroying all Effects, but will keep their React and DOM state.
490+
When an Activity switches from `mode` "visible"` to`"hidden", the `children` will become hidden on the page, and unmount by destroying all Effects, but will keep their React and DOM state.
491491

492-
When the <CodeStep step={2}>mode</CodeStep> later switches to <CodeStep step={4}>visible</CodeStep>, the saved state will be re-used when mounting the children by creating all the Effects. This can be used to keep state in parts of the UI the user is likely to interact with again to maintain DOM or React state.
492+
When the `mode` later switches to "visible", the saved state will be re-used when mounting the children by creating all the Effects. This can be used to keep state in parts of the UI the user is likely to interact with again to maintain DOM or React state.
493493

494-
In the follow example from [`useTransition`](/reference/react/useTransition#preventing-unwanted-loading-indicators), the `ContactsTab` includes a `<textarea>` with a draft message to send. If you enter some text and change to a different tab, then when you click the “Contact” tab again, the draft message is lost:
494+
In the following example from [`useTransition`](/reference/react/useTransition#preventing-unwanted-loading-indicators), the `ContactTab` includes a `<textarea>` with a draft message to send. If you enter some text and change to a different tab, then when you click the “Contact” tab again, the draft message is lost:
495495

496496

497497
<Sandpack>

src/content/reference/react/ViewTransition.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {unstableViewTransition as ViewTransition} from 'react';
4040

4141
### `<ViewTransition>` {/*viewtransition*/}
4242

43-
Wrap elements in `<ViewTransition>` to animate them when they update inside a [Transition](/reference/react/useTransition). React uses [heuristics](#heuristics) to determine if a View Transition activates for an animation:
43+
Wrap elements in `<ViewTransition>` to animate them when they update inside a [Transition](/reference/react/useTransition). React uses the following heuristics to determine if a View Transition activates for an animation:
4444

4545
- `enter`: If a `ViewTransition` itself gets inserted in this Transition, then this will activate.
4646
- `exit`: If a `ViewTransition` itself gets deleted in this Transition, then this will activate.
@@ -101,7 +101,7 @@ Each callback receives as arguments:
101101
- `element`: The DOM element that was animated.
102102
- `types`: The [Transition Types](/reference/react/addTransitionType) included in the animation.
103103

104-
### View Transition Class {/*view-transition-classes*/}
104+
### View Transition Class {/*view-transition-class*/}
105105

106106
The View Transition Class is the CSS class name(s) applied by React during the transition when the ViewTransition activates. It can be a string or an object.
107107
- `string`: the `class` added on the child elements when activated. If `'none'` is provided, no class will be added.
@@ -122,11 +122,11 @@ To customize the animation for a `<ViewTransition>` you can provide a View Trans
122122
For example, to customize an "enter" animation, provide a class name to the `enter` prop:
123123

124124

125-
```js [[1, 1, "enter"], [2, 1, "slide-in"]]
125+
```js
126126
<ViewTransition enter="slide-in">
127127
```
128128

129-
When the ViewTransition activates an <CodeStep step={1}>"enter"</CodeStep> animation, React will add the class name <CodeStep step={2}>slide-in</CodeStep>. Then you can refer to this class using [view transition pseudo selectors](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API#pseudo-elements) to build reusable animations:
129+
When the `<ViewTransition>` activates an "enter" animation, React will add the class name `slide-in`. Then you can refer to this class using [view transition pseudo selectors](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API#pseudo-elements) to build reusable animations:
130130

131131
```css
132132
::view-transition-group(.slide-in) {
@@ -171,9 +171,9 @@ function Parent() {
171171
}
172172
```
173173

174-
When `setShow` is called, `show` switched to `true` and the `Child` component is rendered. Since `setShow` is called inside <CodeStep step={1}>startTransition</CodeStep>, and `Child` renders a <CodeStep step={2}>ViewTransition</CodeStep> before any other DOM nodes, an `enter` animation is triggered.
174+
When `setShow` is called, `show` switches to `true` and the `Child` component is rendered. When `setShow` is called inside `startTransition`, and `Child` renders a `ViewTransition` before any other DOM nodes, an `enter` animation is triggered.
175175

176-
When `show` is switched back to `false`, an `exit` animation is triggered.
176+
When `show` switches back to `false`, an `exit` animation is triggered.
177177

178178
<Sandpack>
179179

0 commit comments

Comments
 (0)