Getting to Know React 19

(beta)

Jim Cummins

Network Access Team

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

What's coming in React 19?

Actions!

New hook: useActionState

React DOM: <form> actions, requestFormReset

New React DOM hook: useFormStatus

New hook: useOptimistic

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

useActionState

State

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

const [actionState, submitAction, isPending] = useActionState(
  async (previousState, formData) => {
     await updateName(String(formData.get("name")));
  }, 
  initialValue
 );
const [value, setValue] = React.useState(initialValue);
<form action={submitAction}>
    <input type="text" name="name" />
    <button type="submit" disabled={isPending}>Update</button>
    {isPending && <Pending />}
</form>

Action state

 

useFormStatus

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

import {useFormStatus} from 'react-dom';

function FutureWoodlandButton() {
  const { pending, data, method, action } = useFormStatus();
  return <button type="submit" disabled={pending} />
}

useOptimistic

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

function ChangeName({currentName, onUpdateName}) {
  const [optimisticName, setOptimisticName] = useOptimistic(currentName);

  const submitAction = async formData => {
    const newName = formData.get("name");
    setOptimisticName(newName);
    const updatedName = await updateName(newName);
    onUpdateName(updatedName);
  };

  return (
    <form action={submitAction}>
      <p>Your name is: {optimisticName}</p>
      <p>
        <label>Change Name:</label>
        <input
          type="text"
          name="name"
          disabled={currentName !== optimisticName}
        />
      </p>
    </form>
  );
}

What (else) is changing?

  • useDeferredValue will have an initial value

  • Wording change: isLoading is becoming isPending

  • Context as a provider instead of Context.Provider

  • ref as a prop, no longer need forwardRef!

  • Cleanup functions for refs

  • New (limited use) API:  use

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

Ref as a prop

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

const MyInput = React.forwardRef((props, ref) => (
  <input placeholder={placeholder} ref={ref} />
));

<MyInput ref={ref} />
function MyInput({placeholder, ref}) {
  return <input placeholder={placeholder} ref={ref} />
}

<MyInput ref={ref} />

Forward Ref

Ref as a prop

Cleanup functions for refs

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

<input
  ref={(ref) => {
    // ref created

    // NEW: return a cleanup function to reset
    // the ref when element is removed from DOM.
    return () => {
      // ref cleanup
    };
  }}
/>

Called when component unmounts

use()

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

import {use} from 'react';

function Comments({commentsPromise}) {
  // `use` will suspend until the promise resolves.
  const comments = use(commentsPromise);
  return comments.map(comment => <p key={comment.id}>{comment}</p>);
}

function Page({commentsPromise}) {
  // When `use` suspends in Comments,
  // this Suspense boundary will be shown.
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Comments commentsPromise={commentsPromise} />
    </Suspense>
  )
}

Probably don't use() this, though

But wait there's more!

  • Support for Custom Elements
  • Better Error Reporting
  • Support for document metadata (title, link, and meta)
  • Stylesheet precedence
  • Support for async scripts
  • Support for preloading resources

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

...and more

  • Server Components
  • Server actions "use server"
  • Improved hydration (server side)

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

Deprecations

  • Removed propTypes and defaultProps
  • Removed string refs
  • Removed legacy context using contextTypes / getChildContext
  • Removed ReactDOM.render, use createRoot instead

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

More deprecations

Remove

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

import {act} from 'react/dom/test-utils'
import {act} from 'react'
react-test-renderer
@testing-library/react

Use

Remove

Use

What isn't in React 19?

  • react-compiler (previously called react-forget)
  • useEffectEvent
  • Built-in Suspense Cache

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

Should I use React 19 today?

  • Probably not in production, yet
  • Will take some time for ecosystem to update
    • types
    • eslint plugins
    • libraries
    • etc.
  • Try it out in playgrounds first, then wait
  • Consider contributing and maintaining a react19 branch to woodland-seed (our app starter repo)
  • Try out the codemods!

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

How to get involved?

  • Frontend Architecture Working Group
  • UI Guild
  • woodland
  • woodland-seed
  • Talk to us about joining Woodland Contributors slack group

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

What to read?

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

Thank you!

https://slides.com/jimthedev/getting-to-know-react-19/fullscreen

Getting to know React 19

By jimthedev

Getting to know React 19

  • 123