В React-приложениях распространенный сценарий — выполнение мутации данных и последующее обновление состояния в ответ. Например, когда пользователь отправляет форму для изменения своего имени, вы делаете API-запрос, а затем обрабатываете ответ. Раньше вам нужно было вручную обрабатывать ожидающие состояния, ошибки, оптимистичные обновления и последовательные запросы.
Например, вы могли бы обрабатывать ожидающее и ошибочное состояние с помощью useState
:
// До 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}>
Обновить
</button>
{error && <p>{error}</p>}
</div>
);
}
В React 19 мы добавляем поддержку использования асинхронных функций в переходах для автоматической обработки ожидающих состояний, ошибок, форм и оптимистичных обновлений.
Например, вы можете использовать useTransition
для обработки ожидающего состояния:
// Использование ожидающего состояния из Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();
const handleSubmit = () => {
startTransition(async () => {
const error = await updateName(name);
if (error) {
setError(error);
return;
}
redirect("/path");
})
};
return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Обновить
</button>
{error && <p>{error}</p>}
</div>
);
}
Асинхронный переход немедленно установит ожидающее состояние в true
, сделает асинхронный запрос(ы) и переключит isPending
на false
после завершения всех переходов. Это позволяет вам сохранить текущий UI отзывчивым и интерактивным, пока данные изменяются.
Примечание:
По соглашению, функции, использующие асинхронные переходы, называются “Actions”.
Actions автоматически управляют отправкой данных для вас:
- Ожидающее состояние: Actions предоставляют ожидающее состояние, которое начинается в начале запроса и автоматически сбрасывается, когда завершается последнее обновление состояния.
- Оптимистичные обновления: Actions поддерживают новый хук
useOptimistic
, чтобы вы могли показывать пользователям мгновенную обратную связь во время отправки запросов. - Обработка ошибок: Actions предоставляют обработку ошибок, чтобы вы могли отображать Error Boundaries, когда запрос завершается неудачно, и автоматически возвращать оптимистичные обновления к их исходному значению.
- Формы: Элементы
<form>
теперь поддерживают передачу функций в свойстваaction
иformAction
. Передача функций в свойствоaction
по умолчанию использует Actions и автоматически сбрасывает форму после отправки.
На основе Actions React 19 вводит useOptimistic
для управления оптимистичными обновлениями и новый хук React.useActionState
для обработки общих случаев для Actions.
В react-dom
мы добавляем <form> Actions
для автоматического управления формами и useFormStatus
для поддержки общих случаев для Actions в формах.
В React 19 приведенный выше пример можно упростить до:
// Использование <form> Actions и useActionState
function ChangeName({ name, setName }) {
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
const error = await updateName(formData.get("name"));
if (error) {
return error;
}
redirect("/path");
return null;
},
null,
);
return (
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>Обновить</button>
{error && <p>{error}</p>}
</form>
);
}