useActionData для доступа к результатам action

useActionData — это хук библиотеки React Router, который позволяет компонентам получать данные, возвращённые из функции action. Он является ключевым инструментом при работе с формами и обработкой запросов на сервер в рамках маршрутизации, позволяя компоненту реагировать на результат отправки данных.


Основы работы с action

В React Router action используется для обработки HTTP-запросов, инициируемых пользователем через формы или программно. Функция action может возвращать любые данные, включая объекты, строки или ошибки, которые затем становятся доступными через useActionData.

Пример определения action:

import { redirect } from "react-router-dom";

export async function createUserAction({ request }) {
  const formData = await request.formData();
  const username = formData.get("username");

  if (!username) {
    return { error: "Имя пользователя обязательно" };
  }

  // Логика сохранения пользователя
  await saveUserToDatabase(username);

  return redirect("/users");
}

В этом примере action возвращает объект с ошибкой, если поле не заполнено, или делает редирект после успешного сохранения. Доступ к результату, если редирект не произошёл, обеспечивается через useActionData.


Использование useActionData

Хук useActionData позволяет компоненту получать данные, возвращённые из action. Он полезен для отображения ошибок, сообщений об успехе или других результатов операции.

import { Form, useActionData } from "react-router-dom";

export default function UserForm() {
  const actionData = useActionData();

  return (
    <Form method="post">
      <input name="username" placeholder="Введите имя пользователя" />
      <button type="submit">Создать</button>
      {actionData?.error && <p style={{ color: "red" }}>{actionData.error}</p>}
    </Form>
  );
}

В этом примере результат action доступен в переменной actionData. Если action возвращает объект с полем error, сообщение об ошибке будет отображено под формой.


Поведение при редиректе

Если action возвращает редирект через функцию redirect(), useActionData не получает данные, потому что маршрут будет немедленно перенаправлен на другой путь. В таких случаях необходимо использовать состояние маршрута или локальное состояние для передачи данных между страницами.


Совместное использование с формами

useActionData особенно полезен при работе с компонентом <Form> из React Router. Метод формы (method) определяет тип запроса, который будет обработан функцией action соответствующего маршрута.

  • Метод POST: чаще всего используется для создания ресурсов и передачи данных на сервер.
  • Метод PUT/PATCH: используется для обновления существующих данных.
  • Метод DELETE: удаляет ресурс, хотя данные обычно не возвращаются, можно возвращать подтверждение операции.

Пример с использованием POST:

import { Form, useActionData } from "react-router-dom";

function LoginForm() {
  const actionData = useActionData();

  return (
    <Form method="post">
      <input name="email" placeholder="Email" />
      <input type="password" name="password" placeholder="Пароль" />
      <button type="submit">Войти</button>
      {actionData?.error && <div className="error">{actionData.error}</div>}
    </Form>
  );
}

Динамическая обработка ошибок

useActionData позволяет динамически реагировать на ошибки валидации, возвращённые из action. Можно проверять наличие конкретных полей и отображать ошибки рядом с соответствующими элементами формы:

const errors = useActionData();

<input name="username" placeholder="Имя пользователя" />
{errors?.username && <span>{errors.username}</span>}

<input name="email" placeholder="Email" />
{errors?.email && <span>{errors.email}</span>}

Такой подход делает формы интерактивными и удобными для пользователя.


Совместное использование с loader

useActionData возвращает данные только после выполнения action. Для первоначальной загрузки данных маршрута используется хук useLoaderData. Совместное применение обоих хуков позволяет компоненту работать как с начальными данными, так и с результатами действий пользователя.

const initialData = useLoaderData();
const actionResult = useActionData();

Таким образом, initialData содержит исходное состояние страницы, а actionResult — результат последнего действия пользователя.


Поддержка TypeScript

useActionData можно типизировать для повышения безопасности кода:

type ActionData = { error?: string; success?: boolean };

const actionData = useActionData<ActionData>();

Теперь TypeScript будет проверять использование полей объекта actionData, уменьшая вероятность ошибок.


Резюме ключевых моментов

  • useActionData возвращает результат последнего вызова action для текущего маршрута.
  • Если action возвращает redirect(), данные не доступны.
  • Совместим с <Form> для обработки форм и ошибок валидации.
  • Можно использовать совместно с useLoaderData для комбинированной загрузки и обработки данных.
  • Поддерживает строгую типизацию через TypeScript.

useActionData является инструментом реактивного взаимодействия с серверной логикой маршрута, обеспечивая прозрачное и гибкое управление состоянием форм и действий.