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
повертає масив, що містить рівно два значення:
- Поточний стан. Під час першого рендерингу він відповідатиме
initialState
, який ви передали. Після виклику дії він відповідатиме значенню, повернутому дією. - Нова дія, яку ви можете передати як проп
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
повертає масив, що містить рівно два елементи:
- Поточний стан
Крок коду</CodeStep> форми, яке початково встановлюється у <CodeStep data-step="4">початковий стан</CodeStep> наданий вами, і після відправки форми встановлюється у значення, що повертається <CodeStep data-step="3">>action</CodeStep> ви надали.</li> <li>A <CodeStep data-step="2">new action</CodeStep> який ви передаєте в <код><форму> як його проп дії
.
При відправці форми виконується дія
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) {
// ...
}