|
| 1 | +--- |
| 2 | +title: "React 19 Beta" |
| 3 | +--- |
| 4 | + |
| 5 | +April 1, 2024 by [The React Team](/community/team) |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +<Intro> |
| 10 | + |
| 11 | +React 19 Beta is now available on npm! |
| 12 | + |
| 13 | +In our [React 19 Upgrade Guide](/blog/04/01/react-19-upgrade-guide), we shared step-by-step instructions for upgrading your app to the React 19 Beta. In this post, we'll give an overview of the new features in React 19 Beta, and how you can adopt them. |
| 14 | + |
| 15 | +_Note for React Native users: React 19 will ship a future version of React Native with the New React Native Architecture._ |
| 16 | + |
| 17 | +</Intro> |
| 18 | + |
| 19 | +<Note> |
| 20 | + |
| 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). |
| 24 | + |
| 25 | +</Note> |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## What's new in React 19 {/*whats-new-in-react-19*/} |
| 30 | + |
| 31 | +### New Feature: Actions {/*new-feature-actions*/} |
| 32 | + |
| 33 | +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: |
| 34 | + |
| 35 | +```js {5,8,10} |
| 36 | +const [name, setName] = useState(''); |
| 37 | +const [error, setError] = useState(null); |
| 38 | + |
| 39 | +// Manually handle the pending state |
| 40 | +const [isPending, setIsPending] = useState(false); |
| 41 | + |
| 42 | +const handleSubmit = async () => { |
| 43 | + setIsPending(true); |
| 44 | + const {error} = await updateName(name); |
| 45 | + setIsPending(false); |
| 46 | + if (error) { |
| 47 | + setError(error); |
| 48 | + } else { |
| 49 | + setName(''); |
| 50 | + } |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +In React 19, we added support for using async functions in transitions: |
| 55 | + |
| 56 | +```js {5,8,15} |
| 57 | +const [name, setName] = useState(''); |
| 58 | +const [error, setError] = useState(null); |
| 59 | + |
| 60 | +// Pending state is handled for you |
| 61 | +const [isPending, startTransition] = useTransition(); |
| 62 | + |
| 63 | +const submitAction = async () => { |
| 64 | + startTransition(async () => { |
| 65 | + const {error} = await updateName(name); |
| 66 | + if (!error) { |
| 67 | + setError(error); |
| 68 | + } else { |
| 69 | + setName(''); |
| 70 | + } |
| 71 | + }) |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +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. |
| 76 | + |
| 77 | +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`: |
| 78 | + |
| 79 | +```js {2,6} |
| 80 | +const [name, setName] = useState(''); |
| 81 | +const [submitAction, data, isPending] = useActionState(async () => { |
| 82 | + return await updateName(name); |
| 83 | + setName(''); |
| 84 | + return result; |
| 85 | +}); |
| 86 | +``` |
| 87 | + |
| 88 | +Actions are enabled by default with the new `<form>` action prop. |
| 89 | + |
| 90 | + |
| 91 | +### New Feature: Forms {/*new-feature-forms*/} |
| 92 | + |
| 93 | +We've added an `action` prop to React DOM `<form>` elements to automatically submit forms with Actions: |
| 94 | + |
| 95 | +```js {11,14} |
| 96 | +const [error, setError] = useState(null); |
| 97 | + |
| 98 | +const submitAction = async (formData) => { |
| 99 | + const {error} = await updateName(formData.get('name')); |
| 100 | + if (error) { |
| 101 | + setError(error); |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +return ( |
| 106 | + <form action={submitAction}> |
| 107 | + <input type="text" name="name" /> |
| 108 | + {error && <span>Failed: {error}</span>} |
| 109 | + </form> |
| 110 | +) |
| 111 | +``` |
| 112 | + |
| 113 | +Actions compose, so to access the pending state of `<form>` actions, you can wrap the action in `startTransition`, or use the `useActionState` hook: |
| 114 | + |
| 115 | +```js {1,3,7-8} |
| 116 | +const [submitAction, state, isPending] = useActionState(async (formData) => { |
| 117 | + return updateName(formData.get('name')); |
| 118 | +}) |
| 119 | + |
| 120 | +return ( |
| 121 | + <form action={submitAction}> |
| 122 | + <input type="text" name="name" disabled={isPending}/> |
| 123 | + {!state.success && <span>Failed: {state.error}</span>} |
| 124 | + </form> |
| 125 | +) |
| 126 | +``` |
| 127 | + |
| 128 | +When a `<form>` Action succeeds, React will automatically reset the form for uncontrolled components. If you need to reset the `<form>` manually, you can call the new `requestFormReset` react-dom API. |
| 129 | + |
| 130 | +Finally, to access the status of the form Action, we've added a new hook `useFormStatus`. This hook works like context for the nearest `<form>` element, returning it's `pending` state and last submitted `formData` and `result`: |
| 131 | + |
| 132 | +```js {2,5-6} |
| 133 | +function NameInput() { |
| 134 | + const {data, pending} = useFormStatus(); |
| 135 | + return ( |
| 136 | + <> |
| 137 | + <input type="text" name="name" disabled={pending} /> |
| 138 | + {!data.sucess && <span>Failed: {data.error}</span>} |
| 139 | + </> |
| 140 | + ) |
| 141 | +} |
| 142 | +``` |
| 143 | + |
| 144 | +### New Feature: Optimistic Updates {/*new-feature-optimistic-updates*/} |
| 145 | + |
| 146 | +### New Feature: Head Elements {/*new-feature-head-elements*/} |
| 147 | + |
| 148 | +### New Feature: Resource Loading APIs {/*new-feature-resource-loading-apis*/} |
| 149 | + |
| 150 | +### React Server Components {/*react-server-components*/} |
| 151 | + |
| 152 | +<Note> |
| 153 | +TODO: Requires a bundler and framework that supports RSC. |
| 154 | +</Note> |
| 155 | + |
| 156 | +## Improvements in React 19 {/*improvements-in-react-19*/} |
| 157 | + |
| 158 | +### Ref as a prop {/*ref-as-a-prop*/} |
| 159 | + |
| 160 | +### Full Support for Web Components {/*support-for-web-components*/} |
| 161 | + |
| 162 | +### Error Handling {/*error-handling*/} |
| 163 | + |
| 164 | +### Strict Mode {/*strict-mode*/} |
| 165 | + |
| 166 | + |
| 167 | +## How to Upgrade {/*how-to-upgrade*/} |
| 168 | +See How to Upgrade to React 18 for step-by-step instructions and a full list of breaking and notable changes. |
| 169 | + |
| 170 | + |
| 171 | + |
0 commit comments