Skip to content

Commit 2813ca9

Browse files
committed
Feedback fixes
1 parent c420621 commit 2813ca9

File tree

2 files changed

+56
-40
lines changed

2 files changed

+56
-40
lines changed

src/content/blog/2024/04/01/react-19-upgrade-guide.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "React 19 Beta Upgrade Guide"
33
---
44

5-
April 1, 2024 by [The React Team](/community/team)
5+
April 1, 2024 by [Ricky Hanlon](https://twitter.com/rickhanlonii)
66

77
---
88

@@ -18,9 +18,7 @@ If you'd like to help us test React 19, follow the steps in this upgrade guide a
1818

1919
<Note>
2020

21-
React Conf 2024 is scheduled for May 15–16 in Henderson, Nevada!
22-
23-
For more see [the React Conf website](https://conf.react.dev).
21+
Stream [React Conf 2024]((https://conf.react.dev)) live May 15–16!
2422

2523
</Note>
2624

src/content/blog/2024/04/01/react-19.md

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ _Note for React Native users: React 19 will ship a future version of React Nativ
3535

3636
<Note>
3737

38-
React Conf 2024 is scheduled for May 15–16 in Henderson, Nevada!
39-
40-
For more see [the React Conf website](https://conf.react.dev).
38+
Stream [React Conf 2024]((https://conf.react.dev)) live May 15–16!
4139

4240
</Note>
4341

@@ -47,7 +45,9 @@ For more see [the React Conf website](https://conf.react.dev).
4745

4846
### Actions {/*actions*/}
4947

50-
A common use case in React apps is to perform a data mutation and then update state in response. For example, when a user submits a form to change their name, you will make an API request, and then handle the response. Since this is an async request, you need to handle the pending state in a separate useState call:
48+
A common use case in React apps is to perform a data mutation and then update state in response. For example, when a user submits a form to change their name, you will make an API request, and then handle the response. In the past, you would need to handle pending states, errors, optimistic updates, and sequential requests manually.
49+
50+
For example, you could handle the pending state in `useState`:
5151

5252
```js {5,8,10}
5353
const [name, setName] = useState('');
@@ -68,7 +68,9 @@ const handleSubmit = async () => {
6868
}
6969
```
7070

71-
In React 19, we added support for using async functions in transitions:
71+
In React 19, we're adding support for using async functions in transitions to handle pending states, errors, forms, and optimistic updates automatically.
72+
73+
For example, you can use `useTransition` to handle the pending state for you:
7274

7375
```js {5,8,15}
7476
const [name, setName] = useState('');
@@ -89,17 +91,33 @@ const submitAction = async () => {
8991
}
9092
```
9193

92-
By convention, functions that use async transitions are called "Actions". Actions will immediately set the `isPending` state to true, make the async request(s), and render any state updates as transitions. This allows you to keep the current UI responsive and interactive while the data is changing.
9394

94-
For more information, see the docs for [`useTransition`](/reference/react/useTransition).
95+
The async transition will immediately set the `isPending` state to true, make the async request(s), and render any state updates as transitions. This allows you to keep the current UI responsive and interactive while the data is changing.
96+
97+
<Note>
98+
99+
#### By convention, functions that use async transitions are called "Actions". {/*by-convention-functions-that-use-async-transitions-are-called-actions*/}
100+
101+
Actions automatically manage submitting data for you:
102+
103+
- **Pending state**: Actions provide a pending state that starts at the beginning of a request and automatically resets when the final state update is committed.
104+
- **Optimistic updates**: Actions support the new [`useOptimistic`](#new-feature-optimistic-updates) hook to handle optimistically showing the user the final state while requests are submitting.
105+
- **Error Handling**: Actions provide error handling so you can and display Error Boundaries when a request fails, and revert optimistic updates to their original value automatically.
106+
- **Forms**: Actions support new `action` prop for `<form>` elements called [Form Actions](#form-actions). This means form submissions use Actions by default, and reset automatically after submission.
107+
108+
</Note>
109+
110+
Async transitions are the raw primitive that power Actions, and you can always drop down to `useTransition`, `useState`, and `useOptimisitc` to create your own custom behavior. We're also introducing the [`useActionState`](#new-hook-useactionstate) and [`useFormStatus`](#new-hook-useformstatus) hooks to support the common cases for Actions and Forms.
111+
112+
For more information, see the docs for [`useTransition`](/reference/react/useTransition) and the next sections.
95113

96114
### New Hook: `useActionState` {/*new-hook-useactionstate*/}
97115

98-
You can always create an Action by dropping down to `useTransition`, but to make the common cases easier we've added a new hook called `useActionState`:
116+
To make the common cases easier for Actions, we've added a new hook called `useActionState`:
99117

100118
```js {2,9}
101119
const [name, setName] = useState('');
102-
const [submitAction, state, isPending] = useActionState(async () => {
120+
const [submitAction, data, isPending] = useActionState(async () => {
103121
const {error} = await updateName(name);
104122
setName('');
105123

@@ -109,7 +127,7 @@ const [submitAction, state, isPending] = useActionState(async () => {
109127
});
110128
```
111129

112-
`useActionState` accepts a function (the "Action"), and returns a new Action to call. This works because Actions compose. When the new Action is called, `useActionState` will return the last result of the Action as `data`, and the pending state of the Action as `pending`.
130+
`useActionState` accepts a function (the "Action"), and returns a wrapped Action to call. This works because Actions compose. When the wrapped Action is called, `useActionState` will return the last result of the Action as `data`, and the pending state of the Action as `pending`.
113131

114132
<Note>
115133

@@ -168,15 +186,15 @@ Another common UI pattern when performing a data mutation is to show the final s
168186
const [name, setName] = useState("");
169187
const [optimisticName, setOptimisticName] = useOptimistic(name);
170188

171-
const handleSubmit = async (formData) => {
189+
const submitAction = async (formData) => {
172190
const newName = formData.get("name");
173191
setOptimisticName(newName);
174192
const updatedName = await updateName(newName);
175193
setName(updatedName);
176194
};
177195

178196
return (
179-
<form action={handleSubmit}>
197+
<form action={submitAction}>
180198
<p>Your name is: {optimisticName}</p>
181199
<p>
182200
<label>Change Name:</label>
@@ -201,10 +219,10 @@ For example, you can read a promise with `use`, and React will Suspend until the
201219
```js {1,6}
202220
import {use} from 'react';
203221

204-
function Comments({loadComments}) {
222+
function Comments({commentsPromise}) {
205223
// NOTE: this will resume the promise from the server.
206224
// It will suspend until the data is available.
207-
const comments = use(loadComments);
225+
const comments = use(commentsPromise);
208226
return comments.map(commment => <p>{comment}</p>);
209227
}
210228
```
@@ -241,7 +259,7 @@ TODO: we can't yet
241259

242260
Server Components are a new option that allows rendering components ahead of time, before bundling, in an environment separate from your application (the "server"). They can run once at build time, or can be run for each request to a web server.
243261

244-
Today we're releasing React Server Components as semver stable in React 19. This means libraries that ship Server Components and Server Action can target React 19 as a peer dependency for use in frameworks that support the [Full-stack React Architecture](/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision).
262+
Today we're releasing React Server Components as semver stable in React 19. This means libraries that ship Server Components and Server Actions can target React 19 as a peer dependency for use in frameworks that support the [Full-stack React Architecture](/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision).
245263

246264
<DeepDive>
247265

@@ -525,13 +543,13 @@ async function Page({id}) {
525543
// Will suspend the Server Component.
526544
const note = await db.notes.get(id);
527545

528-
// NOTE: not awaited, will resume and suspend on the client.
529-
const loadComments = db.comments.get(note.id);
546+
// NOTE: not awaited, will start here and await on the client.
547+
const commentsPromise = db.comments.get(note.id);
530548
return (
531549
<div>
532550
{note}
533551
<Suspense fallback={<p>Loading Comments...</p>}>
534-
<Comments loadComments={loadComments} />
552+
<Comments commentsPromise={commentsPromise} />
535553
</Suspense>
536554
</div>
537555
);
@@ -543,10 +561,10 @@ async function Page({id}) {
543561
"use client";
544562
import {use} from 'react';
545563

546-
function Comments({loadComments}) {
564+
function Comments({commentsPromise}) {
547565
// NOTE: this will resume the promise from the server.
548566
// It will suspend until the data is available.
549-
const comments = use(loadComments);
567+
const comments = use(commentsPromise);
550568
return comments.map(commment => <p>{comment}</p>);
551569
}
552570
```
@@ -575,30 +593,30 @@ TODO
575593

576594
Server Components can define Server Actions with the `"use server"` directive:
577595

578-
```js [[2, 7, "'use server'"], [1, 5, "emptyNoteAction"], [1, 12, "emptyNoteAction"]]
596+
```js [[2, 7, "'use server'"], [1, 5, "createNoteAction"], [1, 12, "createNoteAction"]]
579597
// Server Component
580598
import Button from './Button';
581599

582600
function EmptyNote () {
583-
async function emptyNoteAction() {
601+
async function createNoteAction() {
584602
// Server Action
585603
'use server';
586604

587605
await db.notes.create();
588606
}
589607

590-
return <Button onClick={emptyNoteAction}/>;
608+
return <Button onClick={createNoteAction}/>;
591609
}
592610
```
593611

594-
When React renders the `EmptyNote` Server Component, it will create a reference to the `emptyNoteAction` function, and pass that reference to the `Button` Client Component. When the button is clicked, React will send a request to the server to execute the `emptyNoteAction` function with the reference provided:
612+
When React renders the `EmptyNote` Server Component, it will create a reference to the `createNoteAction` function, and pass that reference to the `Button` Client Component. When the button is clicked, React will send a request to the server to execute the `createNoteAction` function with the reference provided:
595613

596614
```js {5}
597615
"use client";
598616

599617
export default function Button({onClick}) {
600618
console.log(onClick);
601-
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'emptyNoteAction'}
619+
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
602620
return <button onClick={onClick}>Create Empty Note</button>
603621
}
604622
```
@@ -610,25 +628,25 @@ For more, see the docs for [`"use server"`](/reference/react/use-server).
610628

611629
Client Components can import Server Actions from files that use the `"use server"` directive:
612630

613-
```js [[1, 3, "emptyNoteAction"]]
631+
```js [[1, 3, "createNoteAction"]]
614632
"use server";
615633

616-
export async function emptyNoteAction() {
634+
export async function createNoteAction() {
617635
await db.notes.create();
618636
}
619637

620638
```
621639

622-
When the bundler builds the `EmptyNote` Client Component, it will create a reference to the `emptyNoteAction` function in the bundle. When the `button` is clicked, React will send a request to the server to execute the `emptyNoteAction` function using the reference provided:
640+
When the bundler builds the `EmptyNote` Client Component, it will create a reference to the `createNoteAction` function in the bundle. When the `button` is clicked, React will send a request to the server to execute the `createNoteAction` function using the reference provided:
623641

624-
```js [[1, 2, "emptyNoteAction"], [1, 5, "emptyNoteAction"], [1, 7, "emptyNoteAction"]]
642+
```js [[1, 2, "createNoteAction"], [1, 5, "createNoteAction"], [1, 7, "createNoteAction"]]
625643
"use client";
626-
import {emptyNoteAction} from './actions';
644+
import {createNoteAction} from './actions';
627645

628646
function EmptyNote() {
629-
console.log(emptyNoteAction);
630-
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'emptyNoteAction'}
631-
<button onClick={emptyNoteAction} />
647+
console.log(createNoteAction);
648+
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
649+
<button onClick={createNoteAction} />
632650
}
633651
```
634652

@@ -850,7 +868,7 @@ For more, see [Manipulating the DOM with refs](/learn/manipulating-the-dom-with-
850868

851869
We've added an `initalValue` option to `useDeferredValue`:
852870

853-
```js [[1, 1, "deferredValue"], [1, 4, "deferredValue"], [2, 4, "value"], [2, 7, "value"], [3, 4, "''"]]
871+
```js [[1, 1, "deferredValue"], [1, 4, "deferredValue"], [2, 4, "''"]]
854872
function Search({deferredValue}) {
855873
// On inital render the value is ''.
856874
// Then a re-render is scheduled with the deferredValue.
@@ -862,7 +880,7 @@ function Search({deferredValue}) {
862880
}
863881
````
864882

865-
When <CodeStep step={3}>initialValue</CodeStep> is provided, React will return it as the <CodeStep step={2}>value</CodeStep> for the initial render of the component, and scheduled a re-render in the background with the <CodeStep step={1}>deferredValue</CodeStep> returned.
883+
When <CodeStep step={2}>initialValue</CodeStep> is provided, `useDeferredValue` will return it as `value` for the initial render of the component, and scheduled a re-render in the background with the <CodeStep step={1}>deferredValue</CodeStep> returned.
866884

867885
For more, see [`useDeferredValue`](/reference/react/useDeferredValue).
868886

@@ -917,7 +935,7 @@ We've improved hydration to account for third-party scripts and browser extensio
917935

918936
### Better Error Reporting {/*error-handling*/}
919937

920-
We improved error handling in React 19 to remove duplication and provide options for handling caught and uncaught errors. For example, when there's an error in render caught by an error boundary, previously React would throw the error twice (once for the original error, then again after failing to automatically recover), and then call `console.error` with info about where the error occurred.
938+
We improved error handling in React 19 to remove duplication and provide options for handling caught and uncaught errors. For example, when there's an error in render caught by an Error Boundary, previously React would throw the error twice (once for the original error, then again after failing to automatically recover), and then call `console.error` with info about where the error occurred.
921939
922940
This resulted in three errors for every caught error:
923941

0 commit comments

Comments
 (0)