useFormState

Хук useFormState наразі доступний лише в Canary та експериментальних каналах React. Дізнайтеся більше про канали релізів тут. Крім того, вам потрібно використовувати фреймворк, який підтримує Компоненти сервера React, щоб отримати всі переваги useFormState.

useFormState це хук, який дозволяє оновлювати стан на основі результату дії форми.

const [state, formAction] = useFormState(fn, initialState);

Довідник

useFormState(action, initialState)

Викличте useFormState на верхньому рівні вашого компонента, щоб створити стан компонента, який оновлюється коли викликається дія форми. Ви передаєте useFormState існуючу функцію дії форми, а також початковий стан, і вона повертає нову дію, яку ви використовуєте у вашій формі, разом з останнім станом форми. Останній стан форми також передається до функції, яку ви надали.

import { useFormState } from "react-dom";

async function increment(previousState, formData) {
  return previousState + 1;
}

function StatefulForm({}) {
  const [state, formAction] = useFormState(increment, 0);
  return (
    <form>
      {state}
      <button formAction={formAction}>Increment</button>
    </form>
  )
}

Стан форми - це значення, повернуте дією при останньому відправленні форми. Якщо форму ще не було надіслано, ви передаєте початковий стан.

Якщо використовується з дією сервера, useFormState дозволяє показувати відповідь сервера від надсилання форми ще до завершення гідратації.

Дивіться більше прикладів нижче.

Параметри

  • fn: Функція, яка буде викликана при відправці форми або натисканні кнопки. Коли функцію буде викликано, вона отримає попередній стан форми (спочатку initialState, який ви передали, а потім попереднє значення, що повертається) як початковий аргумент, а потім аргументи, які зазвичай отримує дія форми.
  • initialState: Значення, яке ви хочете, щоб стан мав на початку. Це може бути будь-яке значення, яке можна серіалізувати. Цей аргумент ігнорується після першого виклику дії.

Повернення

useFormState повертає масив, що містить рівно два значення:

  1. Поточний стан. Під час першого рендерингу він відповідатиме initialState, який ви передали. Після виклику дії він відповідатиме значенню, повернутому дією.
  2. Нова дія, яку ви можете передати як проп action до вашого компонента форма або formAction до будь-якого компонента кнопка всередині форми.

Застереження

  • При використанні з фреймворком, що підтримує компоненти сервера React, useFormState дозволяє робити форми інтерактивними до того, як JavaScript виконається на стороні клієнта. При використанні без серверних компонентів він еквівалентний локальному стану компонента.
  • Функція, передана до useFormState, отримує додатковий аргумент, попередній або початковий стан, як перший аргумент. Це робить її сигнатуру відмінною від тієї, що була б отримана безпосередньо як дія форми без використання useFormState.

Використання

Використання інформації, повернутої дією форми

Викличте useFormState на верхньому рівні вашого компонента, щоб отримати доступ до значення дії, що повертається з часу останнього надсилання форми.

import { useFormState } from 'react-dom';
import { action } from './actions.js';

function MyComponent() {
  const [state, formAction] = useFormState(action, null);
  // ...
  return (
    <form action={formAction}>
      {/* ... */}
    </form>
  );
}

useFormState повертає масив, що містить рівно два елементи:

  1. Поточний стан Крок коду</CodeStep> форми, яке початково встановлюється у <CodeStep data-step="4">початковий стан</CodeStep> наданий вами, і після відправки форми встановлюється у значення, що повертається <CodeStep data-step="3">>action</CodeStep> ви надали.</li> <li>A <CodeStep data-step="2">new action</CodeStep> який ви передаєте в <код><форму> як його проп дії.

При відправці форми виконується дія CodeStep> буде викликано функцію, яку ви передали. Значенням, яке вона поверне, стане новий <CodeStep data-step="1">поточний стан</CodeStep> форми.</p> <p>The <CodeStep data-step="3">action</CodeStep> , які ви надасте, також отримають новий перший аргумент, а саме <CodeStep data-step="1">поточний стан</CodeStep> форми. При першому відправленні форми це буде <CodeStep data-step="4">початковий стан</CodeStep> ви надали, тоді як при наступних відправленнях це буде значення, що повертається з останнього виклику дії. Решта аргументів такі самі, як якщо б <код>useFormState не використовувався.

function action(currentState, formData) {
  // ...
  return 'next state';
}

Відобразити помилки форми

Щоб відобразити повідомлення, такі як повідомлення про помилку або тост, які повертаються серверною дією, оберніть дію у виклик useFormState.

import { useState } from "react";
import { useFormState } from "react-dom";
import { addToCart } from "./actions.js";

function AddToCartForm({itemID, itemTitle}) {
  const [message, formAction] = useFormState(addToCart, null);
  return (
    <form action={formAction}>
      <h2>{itemTitle}</h2>
      <input type="hidden" name="itemID" value={itemID} />
      <button type="submit">Add to Cart</button>
      {message}
    </form>
  );
}

export default function App() {
  return (
    <>
      <AddToCartForm itemID="1" itemTitle="JavaScript: The Definitive Guide" />
      <AddToCartForm itemID="2" itemTitle="JavaScript: The Good Parts" />
    </>
  )
}
"use server";

export async function addToCart(prevState, queryData) {
  const itemID = queryData.get('itemID');
  if (itemID === "1") {
    return "Added to cart";
  } else {
    return "Couldn't add to cart: the item is sold out.";
  }
}
form {
  border: solid 1px black;
  margin-bottom: 24px;
  padding: 12px
}

form button {
  margin-right: 12px;
}
{
  "dependencies": {
    "react": "canary",
    "react-dom": "canary",
    "react-scripts": "^5.0.0"
  },
  "main": "/index.js",
  "devDependencies": {}
}

Відображення структурованої інформації після надсилання форми

Значення, що повертається з серверної дії, може бути будь-яким серіалізованим значенням. Наприклад, це може бути об'єкт, який містить логічне значення, що вказує на успішність виконання дії, повідомлення про помилку або оновлену інформацію.

import { useState } from "react";
import { useFormState } from "react-dom";
import { addToCart } from "./actions.js";

function AddToCartForm({itemID, itemTitle}) {
  const [formState, formAction] = useFormState(addToCart, {});
  return (
    <form action={formAction}>
      <h2>{itemTitle}</h2>
      <input type="hidden" name="itemID" value={itemID} />
      <button type="submit">Add to Cart</button>
      {formState?.success &&
        <div className="toast">
          Added to cart! Your cart now has {formState.cartSize} items.
        </div>
      }
      {formState?.success === false &&
        <div className="error">
          Failed to add to cart: {formState.message}
        </div>
      }
    </form>
  );
}

export default function App() {
  return (
    <>
      <AddToCartForm itemID="1" itemTitle="JavaScript: The Definitive Guide" />
      <AddToCartForm itemID="2" itemTitle="JavaScript: The Good Parts" />
    </>
  )
}
"use server";

export async function addToCart(prevState, queryData) {
  const itemID = queryData.get('itemID');
  if (itemID === "1") {
    return {
      success: true,
      cartSize: 12,
    };
  } else {
    return {
      success: false,
      message: "The item is sold out.",
    };
  }
}
form {
  border: solid 1px black;
  margin-bottom: 24px;
  padding: 12px
}

form button {
  margin-right: 12px;
}
{
  "dependencies": {
    "react": "canary",
    "react-dom": "canary",
    "react-scripts": "^5.0.0"
  },
  "main": "/index.js",
  "devDependencies": {}
}

Налагодження

Моя дія більше не може прочитати надіслані дані форми

Коли ви обгортаєте дію за допомогою useFormState, вона отримує додатковий аргумент як перший аргумент. Таким чином, передані дані форми є його другим аргументом, а не першим, як це було б зазвичай. Новим першим аргументом, який буде додано, буде поточний стан форми.

function action(currentState, formData) {
  // ...
}