introduce
React v19 has just been released. Today, it is one of the most popular libraries in the world, known for its simplicity and efficient DOM handling. A new edition has been launched this year and here I bring you all the news as always, with practical examples, but in Spanish 👀.
action
Actions are asynchronous transitions you make, such as calling a backend to update state. This new feature makes it easier to manage forms in React and incorporates new hooks such as useTransaction()
:
- How we handled the form before:
// Before Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const handleSubmit = async () => {
setIsPending(true);
const error = await updateName(name);
setIsPending(false);
if (error) {
setError(error);
return;
}
redirect("/path");
};
return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}
- With use
useTransaction()
// Using pending state from Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();
const handleSubmit = () => {
startTransition(async () => {
// Esta transicion es una llamada a una API asincrona
// Aca isPending = true
const error = await updateName(name);
if (error) {
setError(error);
return; // Aca isPending = false
}
redirect("/path"); // Aca isPending = false
});
};
return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}
new hook
Use action states
One way to simplify calls to Actions is to use new hooks useActionState
// Using
function ChangeName({ name, setName }) {
const [error, submitAction, isPending] = useActionState(
// los valores del campo son los nombres de los inputs
async (previousState, formData) => {
// isPending es true
const error = await updateName(formData.get("name"));
if (error) {
return error; // esto settea el error, isPending es false
}
redirect("/path");
return null; // isPending es false
},
null
);
return (
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</form>
);
}
New hook: useOptimistic
new hook useOptimistic
It is used to change the result of a value when a request is made, without waiting for the result and being optimistic about the expected result of the request.
This example shows how to set the name before making the request:
function ChangeName({ currentName, onUpdateName }) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);
const submitAction = async (formData) => {
const newName = formData.get("name");
setOptimisticName(newName); // Aca se muestra el nombre actual antes de confirmarse el cambio
const updatedName = await updateName(newName);
onUpdateName(updatedName); // Aca confirmamos el cambio del nombre
};
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>
);
}
ReactDOM
action
as we are useActionState
form fields can now receive new properties, such as action and formAction, for use ,
y
.
The interesting thing when using actions is that React automatically resets the form when the form is submitted successfully. If you want to reset the form manually you can call requestFormReset
From the React DOM API.
New hook: useFormStatus
Another interesting tool added in this new version of React is hooks useFormStatus
which allows you to use the field isPending
The hook mentioned above. This is useful when we have a loading component, for example. We can use the state of the parent form to show and hide this loading component. The method to use this hook can be as follows:
// Este componente es llamado desde donde se implemente nuestro formulario
import { useFormStatus } from "react-dom";
function LoadingComponent() {
const { pending } = useFormStatus();
return pending ? <>Loading...</> : <>>;
}
useFormStatus
Read the parent form’s state as if it were a context provider.
New API
use
Added in new versions of React use
Read resources at render time.
For example, we can read the promise with: use
React will pause rendering until the promise resolves:
const DataComponent: React.FC = () => {
const user = use(fetchUser()); // fetch user es asincrono
return (
<div>
<h1>{user.name}</h1>
</div>
);
};
export default DataComponent;
SSG and server components
For static site generation (SSG), React has added 2 new APIs:
prerender
prerenderToNodeStream
About server components:
React Server Components allow components to be pre-rendered in an environment separate from the client or SSR server, referred to as the “server” in React Server Components. They can be run once during build on the CI server, or once upon request on the web server. React 19 includes all the functionality of server components, allowing supported libraries to use them as dependencies with export conditions react-server
Para Frameworks con arquitectura Full-end React.
Operation SSR:
Server operations allow client components to call asynchronous functions that execute on the server. When using policies to define server operations use server
the framework automatically creates a reference to the server function and passes it to the client component. When the client calls this function, React sends a request to the server to execute and return the result.
Some improvements in React 19
ref
as a prop
Now you can visit ref
As the backbone of functional components:
import React, { forwardRef, useRef } from "react";
// Aca recibimos ref como prop
const MyInput = forwardRef((props, ref) => {
return <input type="text" placeholder={props.placeholder} ref={ref} />;
});
const MyForm = () => {
const inputRef = useRef(null);
const focusInput = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<form>
<MyInput placeholder="Escribe algo..." ref={inputRef} />
<button type="button" onClick={focusInput}>
Focalizar Input
</button>
</form>
);
};
export default MyForm;
will be removed in the future forwardRef
.
Differences in Hydration Errors
Some bugs in the console when hydrating will also be eliminated (For more information please click here)
as provider
Already used now
quite
:
const CartContext = createContext('');
function App({children}) {
return (
<CartContext value={{ cart, addItem, substractItem, removeItem, cleanCart }}>
{children}
</CartContext>
);
}
Clean up function references
React 19 now supports passing back a function to clear ref
callback:
<input
ref={(ref) => {
// ref es creado
// mi codigo
// Este codigo se ejecuta cuando el componente es quitado del DOM
return () => {
// codigo de limpieza
};
}}
/>
useDeferredValue
Now accept the initial value
A new option has been added to initialize the value of deferredValue
function Search({deferredValue}) {
// El valor inicial es ''
// Se planea un inicio tardio para el valor de query
const value = useDeferredValue(deferredValue, '');
return (
<Results query={value} />
);
}
Metadata support
Now there is new support for metadata in React, which could only be done in tags before. o a traves de librerias:
function BlogPost({post}) {
// En el componente articulo estamos definiendo meta y link, que antes no se podia
return (
<article>
<h1>{post.title}</h1>
<title>{post.title}</title>
<meta name="author" content="Josh" />
<link rel="author" href="https://twitter.com/joshcstory/" />
<meta name="keywords" content={post.keywords} />
<p>
Eee equals em-see-squared...
</p>
</article>
);
}
About style sheets:
Whether external or inline, they need to be placed carefully in the DOM due to precedence rules. This complicates their use in widgets, resulting in loading styles from widgets or using libraries that manage this complexity. React 19 simplifies this process with built-in stylesheet support, allowing you to specify their priority. React manages the insertion order in the DOM and ensures that if they are external, they are loaded before content that depends on them is displayed.
function ComponentOne() {
return (
<Suspense fallback="loading...">
<link rel="stylesheet" href="foo" precedence="default" />
<link rel="stylesheet" href="bar" precedence="high" />
<article class="foo-class bar-class">
{...}
</article>
</Suspense>
)
}
function ComponentTwo() {
// Esta hoja de estilo sera insertada entre foo y bar
// En caso de existir una hoja de estilo igual en otro componente, solo se incluira una
// Ademas se inluyo la posibilidad de renderizar asincrona
return (
<div>
<p>{...}</p>
<link rel="stylesheet" href="baz" precedence="default" />
<link rel="stylesheet" href="bar" async={true} precedence="high" />
</div>
)
}
During server-side rendering (SSR), React includes stylesheets in
Make sure the browser doesn’t draw the content before it’s loaded. If the stylesheet is detected late, React will insert it into the client flow after starting the flow before displaying content that depends on its Suspense boundary. During client-side rendering (CSR), React will wait for the newly rendered stylesheet to load before submitting the render. If the element is rendered in multiple places in the application, React will only include the stylesheet once in the file.
How to update?
There is one to update Update guide React explains in detail how to do it.
Fuente
None of this is my job, this is just a small translation and summary of the English content of this article: react v19
in conclusion
Reading is appreciated and I hope it helps. Some important clarifications:
- I used the examples on the page because they were very clear to me; others I tried to adapt to a more practical example, and still others I generated with my friend GitHub Copilot.
- I used artificial intelligence (my new best friend) to generate a few texts. Any comments or suggestions are always welcome.