<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[React 19: useFormStatus для динамической индикации загрузки форм без лишнего состояния]]></title><description><![CDATA[<p dir="auto"><img src="/assets/uploads/files/a1/8c/ab/1773841717060-generated_1773841678699-resized.webp" alt="Обложка: React 19: useFormStatus для динамической индикации загрузки форм без лишнего состояния" class=" img-fluid img-markdown" /></p>
<p dir="auto">В React 19 появился хук <strong>useFormStatus</strong>, который упрощает работу с формами. Он позволяет отслеживать состояние отправки прямо в дочерних компонентах, без создания дополнительного состояния в родителе. Это решает проблему дублирования loading-логики и делает код чище.</p>
<p dir="auto">Зачем это нужно? Раньше для индикации загрузки приходилось вручную управлять состоянием через useState или Context. Теперь <strong>useFormStatus</strong> дает доступ к pending, data, method и action автоматически. Проблемы с асинхронной отправкой форм уходят на второй план - кнопки отключаются сами, спиннеры показываются без лишнего кода.</p>
<h2>Что возвращает useFormStatus и как это работает</h2>
<p dir="auto">Хук <strong>useFormStatus</strong> вызывается только внутри компонента, вложенного в тег <code>&lt;form&gt;</code>. Он возвращает объект с четырьмя свойствами: <strong>pending</strong> (булево, показывает, идет ли отправка), <strong>data</strong> (FormData с данными формы), <strong>method</strong> (‘get’ или ‘post’) и <strong>action</strong> (URL или функция для отправки). Это позволяет дочерним компонентам реагировать на состояние формы без пропсов или глобального стора.</p>
<p dir="auto">Представьте форму логина: поле email, пароль и кнопка. Во время отправки нужно отключить кнопку и показать ‘Submitting…’. Без <strong>useFormStatus</strong> пришлось бы поднимать состояние вверх. С ним кнопка сама узнает о pending и обновится. Хук работает только с родительской формой - если компонент не внутри <code>&lt;form&gt;</code>, pending всегда false.</p>
<p dir="auto">Вот ключевые свойства в действии:</p>
<ul>
<li><strong>pending: true/false</strong> - основное для спиннеров и отключения элементов. Активируется при submit и деактивируется после завершения действия.</li>
<li><strong>data</strong> - FormData с полями формы. Полезно для превью: ‘Отправляем username: john_doe’.</li>
<li><strong>method</strong> - HTTP-метод формы, по умолчанию ‘get’.</li>
<li><strong>action</strong> - цель отправки, функция или URL.</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Свойство</th>
<th>Тип</th>
<th>Когда использовать</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>pending</strong></td>
<td>boolean</td>
<td>Спиннеры, disabled на кнопках</td>
</tr>
<tr>
<td><strong>data</strong></td>
<td>FormData/null</td>
<td>Превью данных перед отправкой</td>
</tr>
<tr>
<td><strong>method</strong></td>
<td>string</td>
<td>Логика в зависимости от GET/POST</td>
</tr>
<tr>
<td><strong>action</strong></td>
<td>string/function</td>
<td>Динамическая маршрутизация</td>
</tr>
</tbody>
</table>
<h2>Простой пример с кнопкой и загрузкой</h2>
<p dir="auto">Создадим форму регистрации. Родительский компонент содержит <code>&lt;form action={someAction}&gt;</code>, а внутри - отдельный компонент для кнопки. <strong>useFormStatus</strong> в кнопке читает pending и меняет текст/состояние автоматически. Никаких пропсов не нужно передавать.</p>
<p dir="auto">Код выглядит так: импорт из ‘react-dom’, вызов хука в SubmitButton, использование pending для disabled и текста. Во время симуляции API-запроса (setTimeout) кнопка показывает ‘Signing up…’ и блокируется. После успеха или ошибки состояние сбрасывается само. Это избавляет от useState в родителе для loading.</p>
<ul>
<li>Создайте action-функцию с задержкой: <code>async function signupAction(formData) { await new Promise(r =&gt; setTimeout(r, 1000)); return {success: true}; }</code>.</li>
<li>В форме: <code>&lt;form action={formAction}&gt;&lt;input name="email"/&gt;&lt;SubmitButton/&gt;&lt;/form&gt;</code>.<br />
<em>Важно:</em> хук работает только с server actions или form actions в React 19.</li>
</ul>
<pre><code class="language-jsx">function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    &lt;button type="submit" disabled={pending}&gt;
      {pending ? "Отправляем..." : "Зарегистрироваться"}
    &lt;/button&gt;
  );
}
</code></pre>
<h2>Сравнение с традиционным подходом в React 18</h2>
<p dir="auto">В старых версиях формы обрабатывались через onSubmit с useState. Нужно было: setLoading(true) в handleSubmit, fetch, затем setLoading(false). Это создавало boilerplate: состояние, эффекты, обработка ошибок. Плюс Context для дочерних компонентов.</p>
<p dir="auto">С <strong>useFormStatus</strong> + useActionState код сокращается вдвое. Нет ручного управления pending - хук синхронизируется с формой. Для сложных форм (логин + профиль) это спасение: каждый ребенок знает статус без пропсов. Минус - только для DOM-форм, не для кастомных.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Подход</th>
<th>useState (React 18)</th>
<th>useFormStatus (React 19)</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Состояние</strong></td>
<td>Ручное useState</td>
<td>Автоматическое из хука</td>
</tr>
<tr>
<td><strong>Дочерние компоненты</strong></td>
<td>Context/props</td>
<td>Прямой доступ в любом ребенке</td>
</tr>
<tr>
<td><strong>Код</strong></td>
<td>20+ строк</td>
<td>5-10 строк</td>
</tr>
<tr>
<td><strong>Ошибки</strong></td>
<td>setError вручную</td>
<td>Через useActionState</td>
</tr>
</tbody>
</table>
<ul>
<li><em>Традиционный:</em> <code>const [loading, setLoading] = useState(false);</code> + обработчики.</li>
<li><em>Новый:</em> <code>const { pending } = useFormStatus();</code> - и все.</li>
</ul>
<h2>Расширенные сценарии: превью данных и ошибки</h2>
<p dir="auto"><strong>useFormStatus</strong> не только для pending. Свойство data позволяет показывать ‘Запрос username: user123’ прямо на кнопке или рядом. Полезно для подтверждения перед отправкой. Комбинируйте с useOptimistic для мгновенного UI-обновления.</p>
<p dir="auto">В форме имени пользователя: input + кнопка с превью data?.get(‘username’). Во время отправки input disabled={pending}. После - показ результата из action. Это создает отзывчивый интерфейс без лишнего состояния. Для ошибок используйте useActionState параллельно.</p>
<ul>
<li>Превью на кнопке: <code>{data &amp;&amp; &lt;span&gt;Отправка: ${data.get('name')}&lt;/span&gt;}</code>.</li>
<li><em>Блокировка полей:</em> <code>disabled={pending}</code> на input.</li>
<li>Комбо с useActionState: <code>[state, formAction] = useActionState(actionFn, initialState)</code>.</li>
</ul>
<pre><code class="language-jsx">function UsernamePreview() {
  const { pending, data } = useFormStatus();
  return (
    &lt;p&gt;{pending &amp;&amp; data ? `Запрашиваем ${data.get('username')}...` : ''}&lt;/p&gt;
  );
}
</code></pre>
<h2>Когда хук не сработает и как фиксить</h2>
<p dir="auto"><strong>useFormStatus</strong> возвращает pending: false всегда, если компонент не внутри <code>&lt;form&gt;</code>. Проверьте в DevTools: хук ищет ближайшую родительскую форму. Решение - обернуть в form или переместить компонент внутрь.</p>
<p dir="auto">Еще проблема: кастомные кнопки без type=“submit”. Укажите тип явно. Для SSR pending может отставать - используйте Suspense. Тестируйте в production-билде, симулируя медленный fetch.</p>
<ul>
<li><em>Не вложен в form:</em> Переместите компонент внутрь.</li>
<li><em>Не срабатывает submit:</em> Проверьте action на сервере.</li>
<li>Несовместимость с библиотеками вроде react-hook-form - пока экспериментально.</li>
</ul>
<h2>Хук в экосистеме React 19 форм</h2>
<p dir="auto"><strong>useFormStatus</strong> идеально сочетается с useActionState и useOptimistic. Вместе они заменяют весь boilerplate для форм: состояние, loading, оптимистичные обновления. Для больших приложений это норма - меньше багов, чище код. Остается экспериментировать с data для кастомных превью и думать, как интегрировать с TypeScript для типизации FormData.</p>
]]></description><link>https://forum.exlends.ru/topic/1733/react-19-useformstatus-dlya-dinamicheskoj-indikacii-zagruzki-form-bez-lishnego-sostoyaniya</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 03:52:34 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/1733.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 18 Mar 2026 13:48:37 GMT</pubDate><ttl>60</ttl></channel></rss>