Формы, ревалидация и обновление данных
Закрываем цикл: отправили форму на сервер — и сразу видим свежие данные на странице.
После мутации через Server Action кэш нужно сбросить функциями
revalidatePathилиrevalidateTag, иначе пользователь увидит старые данные из кэша.
Проблема устаревших данных
Next.js агрессивно кэширует. Если вы добавили запись через Server Action, но не сказали фреймворку «данные изменились», страница со списком может показать прежнее содержимое. Решение — ревалидация после мутации.
// app/todos/actions.ts
"use server";
import { revalidatePath } from "next/cache";
import { db } from "@/lib/db";
export async function addTodo(formData) {
const text = formData.get("text");
await db.todos.create({ data: { text } });
revalidatePath("/todos"); // сбросить кэш страницы списка
}
После revalidatePath("/todos") Next.js перерисует список с учётом новой записи.
Два инструмента ревалидации
| Функция | Что сбрасывает |
revalidatePath("/todos") | Кэш конкретного маршрута |
revalidateTag("todos") | Все запросы, помеченные тегом todos |
Теги удобны, когда одни и те же данные используются на нескольких страницах: пометили fetch тегом — и одним вызовом обновили их везде.
Состояние отправки формы
Чтобы заблокировать кнопку на время отправки, в клиентском компоненте используют хук useFormStatus:
"use client";
import { useFormStatus } from "react-dom";
export default function SubmitButton() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "Сохраняем…" : "Сохранить"}
</button>
);
}
Полный цикл
Соберём логику воедино на простой модели «состояние списка после действия»:
let todos = ["купить хлеб"];
function addTodo(text) {
todos = [...todos, text]; // мутация на «сервере»
return "revalidate:/todos"; // сигнал обновить страницу
}
console.log(addTodo("позвонить маме"));
console.log("Список теперь:", todos);
Вывод:
revalidate:/todos Список теперь: [ 'купить хлеб', 'позвонить маме' ]
Итог
- После мутации вызывайте
revalidatePathилиrevalidateTag, иначе данные останутся старыми. - Теги удобны, когда одни данные нужны на нескольких страницах.
useFormStatusдаёт состояниеpendingдля блокировки кнопки отправки.
Проверьте себя
1. Зачем после Server Action вызывать revalidatePath?
AЧтобы отправить форму
BЧтобы сбросить кэш и показать обновлённые данные
CЧтобы перейти на другую страницу
DЧтобы залогировать запрос
2. Когда удобнее использовать revalidateTag вместо revalidatePath?
AКогда одни и те же данные используются на нескольких страницах
BКогда нужно обновить CSS
CКогда форма клиентская
DНикогда — это одно и то же
3. Что даёт хук useFormStatus?
AТекст ошибки формы
BФлаг pending — идёт ли отправка формы прямо сейчас
CСписок полей формы
DURL текущей страницы