Дізнайтесь про потокову передачу відповідей React Server Actions для прогресивних форм. Навчіться створювати швидші, більш чутливі форми для кращого досвіду користувача.
Потокова передача відповідей React Server Actions: Прогресивна відповідь форми для покращеного UX
React Server Actions представляють потужну зміну парадигми в тому, як ми обробляємо операції на стороні сервера в наших React-додатках. Однією з найцікавіших можливостей є здатність потоково передавати відповіді, що дозволяє нам надавати миттєвий зворотний зв'язок користувачам ще до завершення всієї операції. Це особливо корисно для форм, де ми можемо створити більш чутливий та захоплюючий досвід користувача, оновлюючи інтерфейс у міру надходження даних.
Розуміння React Server Actions
Server Actions — це асинхронні функції, що виконуються на сервері, ініційовані з компонентів React. Вони пропонують кілька переваг над традиційними API-викликами:
- Покращена безпека: Server Actions виконуються безпосередньо на сервері, зменшуючи ризик витоку конфіденційних даних або логіки на клієнт.
- Зменшення шаблонного коду: Вони усувають потребу в окремих API-маршрутах та логіці отримання даних на клієнті.
- Підвищена продуктивність: Вони можуть використовувати рендеринг на стороні сервера (SSR) та кешування для швидшого початкового завантаження та покращеної продуктивності.
- Типова безпека: З TypeScript, Server Actions забезпечують наскрізну типову безпеку, гарантуючи узгодженість даних між клієнтом та сервером.
Сила потокової передачі відповідей
Традиційні відправки форм часто включають надсилання всіх даних на сервер, очікування відповіді, а потім відповідне оновлення інтерфейсу. Це може призвести до відчутної затримки, особливо для складних форм або повільних мережевих з'єднань. Потокова передача відповіді дозволяє серверу надсилати дані клієнту частинами, що дає змогу прогресивно оновлювати інтерфейс у міру надходження даних.
Уявіть собі форму, яка розраховує складну ціну на основі введених користувачем даних. Замість того, щоб чекати завершення всього розрахунку, сервер може потоково передавати проміжні результати клієнту, надаючи користувачеві зворотний зв'язок у реальному часі. Це може значно покращити досвід користувача та зробити додаток більш чутливим.
Реалізація прогресивної відповіді форми за допомогою Server Actions
Давайте розглянемо приклад того, як реалізувати прогресивну відповідь форми за допомогою React Server Actions.
Приклад: Конвертер валют у реальному часі
Ми створимо просту форму конвертера валют, яка надає оновлення обмінного курсу в реальному часі, коли користувач вводить суму.
1. Налаштування Server Action
Спочатку ми визначимо Server Action, яка обробляє конвертацію валют.
// server/actions.ts
'use server';
import { unstable_cache } from 'next/cache';
async function getExchangeRate(fromCurrency: string, toCurrency: string): Promise<number> {
// Simulate fetching exchange rate from an external API
console.log(`Fetching exchange rate for ${fromCurrency} to ${toCurrency}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate network delay
if (fromCurrency === 'USD' && toCurrency === 'EUR') return 0.92;
if (fromCurrency === 'EUR' && toCurrency === 'USD') return 1.09;
if (fromCurrency === 'USD' && toCurrency === 'JPY') return 145;
if (fromCurrency === 'JPY' && toCurrency === 'USD') return 0.0069;
throw new Error(`Exchange rate not found for ${fromCurrency} to ${toCurrency}`);
}
export const convertCurrency = async (prevState: any, formData: FormData) => {
const fromCurrency = formData.get('fromCurrency') as string;
const toCurrency = formData.get('toCurrency') as string;
const amount = Number(formData.get('amount'));
try {
if (!fromCurrency || !toCurrency || isNaN(amount)) {
return { message: 'Please provide valid input.' };
}
// Simulate streaming the response
await new Promise(resolve => setTimeout(resolve, 250));
const exchangeRate = await unstable_cache(
async () => getExchangeRate(fromCurrency, toCurrency),
[`exchange-rate-${fromCurrency}-${toCurrency}`],
{ tags: [`exchange-rate-${fromCurrency}-${toCurrency}`] }
)();
await new Promise(resolve => setTimeout(resolve, 250));
const convertedAmount = amount * exchangeRate;
return { message: `Converted amount: ${convertedAmount.toFixed(2)} ${toCurrency}` };
} catch (e: any) {
console.error(e);
return { message: 'Failed to convert currency.' };
}
};
У цьому прикладі Server Action convertCurrency
отримує обмінний курс (імітується із затримкою) і розраховує конвертовану суму. Ми додали штучні затримки за допомогою setTimeout
, щоб імітувати мережеву затримку та продемонструвати ефект потокової передачі.
2. Реалізація компонента React
Далі ми створюємо компонент React, який використовує Server Action.
// app/page.tsx
'use client';
import { useState, useTransition } from 'react';
import { convertCurrency } from './server/actions';
import { useFormState } from 'react-dom';
export default function CurrencyConverter() {
const [fromCurrency, setFromCurrency] = useState('USD');
const [toCurrency, setToCurrency] = useState('EUR');
const [amount, setAmount] = useState('');
const [isPending, startTransition] = useTransition();
const [state, formAction] = useFormState(convertCurrency, { message: '' });
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
startTransition(() => {
formAction(new FormData(event.target as HTMLFormElement));
});
};
return (
<div>
<h2>Real-Time Currency Converter</h2>
<form action={handleSubmit}>
<label htmlFor="fromCurrency">From:</label>
<select id="fromCurrency" name="fromCurrency" value={fromCurrency} onChange={(e) => setFromCurrency(e.target.value)}>
<option value="USD">USD</option>
<option value="EUR">EUR</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="toCurrency">To:</label>
<select id="toCurrency" name="toCurrency" value={toCurrency} onChange={(e) => setToCurrency(e.target.value)}>
<option value="EUR">EUR</option>
<option value="USD">USD</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="amount">Amount:</label>
<input
type="number"
id="amount"
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button type="submit" disabled={isPending}>
{isPending ? 'Converting...' : 'Convert'}
</button>
</form>
<p>{state.message}</p>
</div>
);
}
Ключові моменти:
- Ми використовуємо хук
useFormState
для керування станом форми та виклику Server Action. - Стан
isPending
зuseTransition
деактивує кнопку відправки та показує повідомлення "Конвертація...", поки дія виконується, надаючи користувачеві зворотний зв'язок. - Функція
formAction
, що повертаєтьсяuseFormState
, автоматично обробляє відправку форми та оновлює стан відповіддю від Server Action.
3. Розуміння прогресивних оновлень
Коли користувач відправляє форму, викликається функція handleSubmit
. Вона створює об'єкт FormData
з форми і передає його у функцію formAction
. Потім Server Action виконується на сервері. Через штучні затримки, введені в Server Action, ви спостерігатимете наступне:
- Кнопка відправки майже миттєво змінюється на "Конвертація...".
- Після короткої затримки (250 мс) код імітує отримання обмінного курсу.
- Конвертована сума розраховується, і результат надсилається назад клієнту.
state.message
у компоненті React оновлюється, відображаючи конвертовану суму.
Це демонструє, як потокова передача відповіді дозволяє нам надавати проміжні оновлення користувачеві в міру надходження даних, що призводить до більш чутливого та захоплюючого досвіду користувача.
Переваги прогресивної відповіді форми
- Покращений досвід користувача: Надає миттєвий зворотний зв'язок користувачам, роблячи додаток більш чутливим і менш повільним.
- Зменшення відчутної затримки: Показуючи проміжні результати, користувачі сприймають процес як швидший, навіть якщо загальна операція займає стільки ж часу.
- Підвищена залученість: Утримує увагу користувачів, надаючи оновлення в реальному часі та запобігаючи відмові від заповнення форми через відчутні затримки.
- Збільшення коефіцієнта конверсії: Більш плавний та чутливий досвід користувача може призвести до вищих коефіцієнтів конверсії, особливо для складних форм.
Просунуті техніки
1. Використання `useOptimistic` для миттєвих оновлень UI
Хук useOptimistic
дозволяє вам оптимістично оновлювати UI до завершення Server Action. Це може забезпечити ще швидший час відгуку, оскільки UI негайно відображає очікуваний результат.
import { useOptimistic } from 'react';
function MyComponent() {
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(state, newUpdate) => {
// Return the new state based on the update
return { ...state, ...newUpdate };
}
);
const handleClick = async () => {
addOptimistic({ someValue: 'optimistic update' });
await myServerAction();
};
return (
<div>
<p>{optimisticState.someValue}</p>
<button onClick={handleClick}>Update</button>
</div>
);
}
У прикладі з конвертером валют ви могли б оптимістично оновити конвертовану суму на основі поточного обмінного курсу, надаючи користувачеві миттєвий попередній перегляд до того, як фактичний розрахунок завершиться на сервері. Якщо сервер повертає помилку, ви можете скасувати оптимістичне оновлення.
2. Реалізація обробки помилок та механізмів відкату
Вкрай важливо реалізувати надійну обробку помилок та механізми відкату для випадків, коли Server Action зазнає невдачі або переривається мережеве з'єднання. Ви можете використовувати блок try...catch
всередині Server Action, щоб перехоплювати помилки та повертати відповідне повідомлення про помилку клієнту.
// server/actions.ts
export const convertCurrency = async (prevState: any, formData: FormData) => {
// ...
try {
// ...
} catch (error: any) {
console.error(error);
return { message: 'An error occurred while converting the currency. Please try again later.' };
}
};
На стороні клієнта ви можете відобразити повідомлення про помилку користувачеві та надати опції для повторної спроби операції або звернення до служби підтримки.
3. Кешування обмінних курсів для продуктивності
Отримання обмінних курсів із зовнішнього API може стати вузьким місцем у продуктивності. Щоб покращити продуктивність, ви можете кешувати обмінні курси, використовуючи механізм кешування, такий як Redis або Memcached. Функція unstable_cache
з Next.js (як використано в прикладі) надає вбудоване рішення для кешування. Не забувайте періодично інвалідувати кеш, щоб забезпечити актуальність обмінних курсів.
4. Аспекти інтернаціоналізації
При створенні додатків для глобальної аудиторії важливо враховувати інтернаціоналізацію (i18n). Це включає:
- Форматування чисел: Використовуйте відповідні формати чисел для різних локалей (наприклад, використання коми або крапки як десяткового роздільника).
- Форматування валют: Відображайте символи та формати валют відповідно до локалі користувача.
- Форматування дати та часу: Використовуйте відповідні формати дати та часу для різних локалей.
- Локалізація: Перекладайте інтерфейс користувача на різні мови.
Бібліотеки, такі як Intl
та react-intl
, можуть допомогти вам реалізувати i18n у ваших React-додатках.
Реальні приклади та випадки використання
- Електронна комерція: Відображення вартості доставки та приблизних термінів у реальному часі, коли користувач додає товари до кошика.
- Фінансові додатки: Надання котирувань акцій та оновлень портфеля в реальному часі.
- Бронювання подорожей: Показ цін на авіаквитки та їх наявності в реальному часі.
- Візуалізація даних: Потокова передача оновлень даних для діаграм та графіків.
- Інструменти для співпраці: Відображення оновлень документів та проєктів у реальному часі.
Висновок
Потокова передача відповідей React Server Actions пропонує потужний спосіб покращити досвід користувача у ваших React-додатках. Надаючи прогресивні відповіді форм, ви можете створювати швидші, більш чутливі та захоплюючі форми, які утримують увагу користувачів та збільшують коефіцієнт конверсії. Поєднуючи потокову передачу відповідей з такими техніками, як оптимістичні оновлення та кешування, ви можете створювати дійсно виняткові користувацькі досвіди.
Оскільки React Server Actions продовжують розвиватися, ми можемо очікувати появи ще потужніших функцій та можливостей, які ще більше спростять розробку складних та динамічних веб-додатків.
Подальше вивчення
Цей посібник надає всебічний огляд потокової передачі відповідей React Server Actions та її застосування для прогресивних відповідей форм. Розуміючи концепції та техніки, обговорені тут, ви зможете використати цю потужну функцію для створення швидших, більш чутливих та захоплюючих веб-додатків.