useActionState
Чтобы упростить общие случаи для actions функций, был добавлен новый хук под названием useActionState
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);
useActionState
позволяет сразу получить состояние (его можно использовать для success уведомления или ошибки), создать action для обработки формы (он его принимает при вызове), и возвращает состояние isPending.
Функция, которую принимает useActionState
должна иметь 2 параметра prevState
и formData
.
Рассмотрим на простом примере со счетчиком:
import { useActionState } from "react";
async function increment(previousState, formData) {
return previousState + 1;
}
export default function App({}) {
const [state, formAction] = useActionState(increment, 0);
return (
<form>
<div className="fs-3 mb-2">{state}</div>
<button formAction={formAction} className="btn btn-dark">
Increment
</button>
</form>
);
}
И на примере с формой обновления имени. Обратите внимание. Так как useActionState имеет состояние формы, то мы избавились от состояния success. И у нас теперь есть состояние формы в которое записывается информация об отправке формы. В этом состоянии может быть информация как об ошибке, так и о успехе.
import { useActionState } from "react";
async function updateName() {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 2000);
});
console.log("updateName COMPLETE");
return {
success: true,
message: "Some error text",
};
}
function App() {
const [formState, submitAction, isPending] = useActionState(handleSubmit, null);
async function handleSubmit (prevState, formData) {
console.log(formData.get("name"));
return await updateName(name);
};
function showSuccess() {
return <div className="alert alert-success mb-3">Form submited!</div>;
}
return (
<form action={submitAction} className="card shadow p-3">
{formState?.success && showSuccess()}
{formState?.success === false && <p>{formState.message}</p>}
<label className="form-label">Enter name</label>
<input name="name" className="form-control mb-3" />
<button className="btn btn-dark" disabled={isPending}>
Update
</button>
</form>
);
}
export default App;