Atklājiet React useActionState āķa jaudu. Uzziniet, kā tas vienkāršo formu pārvaldību, apstrādā gaidīšanas stāvokļus un uzlabo lietotāja pieredzi ar praktiskiem piemēriem.
React useActionState: Visaptveroša rokasgrāmata modernai formu pārvaldībai
Tīmekļa izstrādes pasaule nepārtraukti attīstās, un React ekosistēma ir šo pārmaiņu priekšgalā. Ar jaunākajām versijām React ir ieviesis jaudīgas funkcijas, kas fundamentāli uzlabo veidu, kā mēs veidojam interaktīvas un noturīgas lietojumprogrammas. Viena no ietekmīgākajām no tām ir useActionState āķis, kas maina spēles noteikumus formu un asinhrono operāciju apstrādē. Šis āķis, kas iepriekš eksperimentālajās versijās bija pazīstams kā useFormState, tagad ir stabils un būtisks rīks jebkuram modernam React izstrādātājam.
Šī visaptverošā rokasgrāmata jūs aizvedīs dziļā useActionState izpētē. Mēs izpētīsim problēmas, kuras tas risina, tā pamatmehāniku un to, kā to izmantot kopā ar papildinošiem āķiem, piemēram, useFormStatus, lai radītu izcilu lietotāja pieredzi. Neatkarīgi no tā, vai veidojat vienkāršu saziņas formu vai sarežģītu, datu ietilpīgu lietojumprogrammu, useActionState izpratne padarīs jūsu kodu tīrāku, deklaratīvāku un robustāku.
Problēma: Tradicionālās formu stāvokļa pārvaldības sarežģītība
Lai mēs spētu novērtēt useActionState eleganci, mums vispirms ir jāsaprot izaicinājumi, kurus tas risina. Gadiem ilgi formu stāvokļa pārvaldība React ietvēra paredzamu, bet bieži vien apgrūtinošu modeli, izmantojot useState āķi.
Apskatīsim bieži sastopamu scenāriju: vienkārša forma, lai pievienotu jaunu produktu sarakstam. Mums ir jāpārvalda vairāki stāvokļa elementi:
- Ievades vērtība produkta nosaukumam.
- Ielādes vai gaidīšanas stāvoklis, lai sniegtu lietotājam atgriezenisko saiti API izsaukuma laikā.
- Kļūdas stāvoklis, lai parādītu ziņojumus, ja iesniegšana neizdodas.
- Veiksmes stāvoklis vai ziņojums pēc pabeigšanas.
Tipiska implementācija varētu izskatīties apmēram šādi:
Piemērs: 'Vecais veids' ar vairākiem useState āķiem
// Fiktīva API funkcija
const addProductAPI = async (productName) => {
await new Promise(resolve => setTimeout(resolve, 1500));
if (!productName || productName.length < 3) {
throw new Error('Produkta nosaukumam jābūt vismaz 3 rakstzīmes garam.');
}
console.log(`Produkts "${productName}" pievienots.`);
return { success: true };
};
// Komponents
{error}import { useState } from 'react';
function OldProductForm() {
const [productName, setProductName] = useState('');
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const handleSubmit = async (event) => {
event.preventDefault();
setIsPending(true);
setError(null);
try {
await addProductAPI(productName);
setProductName(''); // Notīrīt ievadi pēc veiksmīgas darbības
} catch (err) {
setError(err.message);
} finally {
setIsPending(false);
}
};
return (
id="productName"
name="productName"
value={productName}
onChange={(e) => setProductName(e.target.value)}
/>
{isPending ? 'Pievieno...' : 'Pievienot produktu'}
{error &&
);
}
Šī pieeja darbojas, bet tai ir vairāki trūkumi:
- Lieks kods (Boilerplate): Mums ir nepieciešami trīs atsevišķi useState izsaukumi, lai pārvaldītu to, kas konceptuāli ir viens formas iesniegšanas process.
- Manuāla stāvokļa pārvaldība: Izstrādātājs ir atbildīgs par manuālu ielādes un kļūdu stāvokļu iestatīšanu un atiestatīšanu pareizajā secībā try...catch...finally blokā. Tas ir atkārtots un pakļauts kļūdām.
- Sasaiste: Loģika formas iesniegšanas rezultāta apstrādei ir cieši saistīta ar komponenta renderēšanas loģiku.
Iepazīstinām ar useActionState: Paradigmas maiņa
useActionState ir React āķis, kas īpaši izstrādāts, lai pārvaldītu asinhronas darbības stāvokli, piemēram, formas iesniegšanu. Tas racionalizē visu procesu, savienojot stāvokli tieši ar darbības funkcijas rezultātu.
Tā paraksts ir skaidrs un kodolīgs:
const [state, formAction] = useActionState(actionFn, initialState);
Sadalīsim tā komponentus:
actionFn(previousState, formData)
: Šī ir jūsu asinhronā funkcija, kas veic darbu (piemēram, izsauc API). Tā saņem iepriekšējo stāvokli un formas datus kā argumentus. Būtiski, ka tas, ko šī funkcija atgriež, kļūst par jauno stāvokli.initialState
: Šī ir stāvokļa vērtība pirms darbības pirmās izpildes.state
: Šis ir pašreizējais stāvoklis. Sākotnēji tas satur initialState un pēc katras izpildes tiek atjaunināts ar jūsu actionFn atgriezto vērtību.formAction
: Šī ir jauna, ietīta jūsu darbības funkcijas versija. Šī funkcija jāpadod<form>
elementaaction
īpašībai. React izmanto šo ietīto funkciju, lai izsekotu darbības gaidīšanas stāvokli.
Praktisks piemērs: Pārveidošana ar useActionState
Tagad pārveidosim mūsu produkta formu, izmantojot useActionState. Uzlabojums ir nekavējoties pamanāms.
Pirmkārt, mums jāpielāgo mūsu darbības loģika. Tā vietā, lai mestu kļūdas, darbībai jāatgriež stāvokļa objekts, kas apraksta rezultātu.
Piemērs: 'Jaunais veids' ar useActionState
// Darbības funkcija, kas paredzēta darbam ar useActionState
const addProductAction = async (previousState, formData) => {
const productName = formData.get('productName');
await new Promise(resolve => setTimeout(resolve, 1500)); // Simulēt tīkla aizkavi
if (!productName || productName.length < 3) {
return { message: 'Produkta nosaukumam jābūt vismaz 3 rakstzīmes garam.', success: false };
}
console.log(`Produkts "${productName}" pievienots.`);
// Veiksmes gadījumā atgriezt veiksmes ziņojumu un notīrīt formu.
return { message: `Veiksmīgi pievienots "${productName}"`, success: true };
};
// Pārveidotais komponents
{state.message} {state.message}import { useActionState } from 'react';
// Piezīme: Nākamajā sadaļā pievienosim useFormStatus, lai apstrādātu gaidīšanas stāvokli.
function NewProductForm() {
const initialState = { message: null, success: false };
const [state, formAction] = useActionState(addProductAction, initialState);
return (
{!state.success && state.message && (
)}
{state.success && state.message && (
)}
);
}
Paskatieties, cik tas ir tīrāks! Mēs esam aizstājuši trīs useState āķus ar vienu useActionState āķi. Komponenta atbildība tagad ir tikai renderēt UI, pamatojoties uz `state` objektu. Visa biznesa loģika ir glīti iekapsulēta `addProductAction` funkcijā. Stāvoklis tiek atjaunināts automātiski, pamatojoties uz to, ko atgriež darbība.
Bet pagaidiet, kā ar gaidīšanas stāvokli? Kā mēs atspējosim pogu, kamēr forma tiek iesniegta?
Gaidīšanas stāvokļu apstrāde ar useFormStatus
React nodrošina pavadošo āķi, useFormStatus, kas paredzēts tieši šīs problēmas risināšanai. Tas sniedz statusa informāciju par pēdējo formas iesniegšanu, bet ar kritisku noteikumu: tam jābūt izsauktam no komponenta, kas tiek renderēts iekšā <form>
, kura statusu vēlaties izsekot.
Tas veicina tīru atbildības sadalīšanu. Jūs izveidojat komponentu īpaši tiem UI elementiem, kuriem jābūt informētiem par formas iesniegšanas statusu, piemēram, iesniegšanas pogai.
useFormStatus āķis atgriež objektu ar vairākām īpašībām, no kurām svarīgākā ir `pending`.
const { pending, data, method, action } = useFormStatus();
pending
: Būla vērtība, kas ir `true`, ja vecākā forma pašlaik tiek iesniegta, un `false` pretējā gadījumā.data
: `FormData` objekts, kas satur iesniedzamos datus.method
: Virkne, kas norāda HTTP metodi (`'get'` vai `'post'`).action
: Atsauce uz funkciju, kas tika padota formas `action` īpašībai.
Stāvokli zinošas iesniegšanas pogas izveide
Izveidosim īpašu `SubmitButton` komponentu un integrēsim to mūsu formā.
Piemērs: SubmitButton komponents
import { useFormStatus } from 'react-dom';
// Piezīme: useFormStatus tiek importēts no 'react-dom', nevis 'react'.
function SubmitButton() {
const { pending } = useFormStatus();
return (
{pending ? 'Pievieno...' : 'Pievienot produktu'}
);
}
Tagad mēs varam atjaunināt mūsu galveno formas komponentu, lai to izmantotu.
Piemērs: Pilnīga forma ar useActionState un useFormStatus
{state.message} {state.message}import { useActionState } from 'react';
import { useFormStatus } from 'react-dom';
// ... (addProductAction funkcija paliek tāda pati)
function SubmitButton() { /* ... kā definēts iepriekš ... */ }
function CompleteProductForm() {
const initialState = { message: null, success: false };
const [state, formAction] = useActionState(addProductAction, initialState);
return (
{/* Mēs varam pievienot atslēgu (key), lai atiestatītu ievadi pēc veiksmīgas darbības */}
{!state.success && state.message && (
)}
{state.success && state.message && (
)}
);
}
Ar šo struktūru `CompleteProductForm` komponentam nav nepieciešams zināt neko par gaidīšanas stāvokli. `SubmitButton` ir pilnībā pašpietiekams. Šis kompozicionālais modelis ir neticami spēcīgs sarežģītu, uzturamu UI veidošanai.
Progresīvās uzlabošanas spēks
Viena no dziļākajām priekšrocībām šai jaunajai uz darbībām balstītajai pieejai, īpaši, ja to izmanto ar servera darbībām (Server Actions), ir automātiska progresīvā uzlabošana. Tas ir vitāli svarīgs koncepts, veidojot lietojumprogrammas globālai auditorijai, kur tīkla apstākļi var būt neuzticami un lietotājiem var būt vecākas ierīces vai atspējots JavaScript.
Lūk, kā tas darbojas:
- Bez JavaScript: Ja lietotāja pārlūkprogramma neizpilda klienta puses JavaScript, `<form action={...}>` darbojas kā standarta HTML forma. Tā veic pilnas lapas pieprasījumu uz serveri. Ja izmantojat ietvaru kā Next.js, servera puses darbība tiek izpildīta, un ietvars atkārtoti renderē visu lapu ar jauno stāvokli (piemēram, parādot validācijas kļūdu). Lietojumprogramma ir pilnībā funkcionāla, tikai bez SPA līdzīgās plūstamības.
- Ar JavaScript: Tiklīdz JavaScript pakotne ielādējas un React hidratē lapu, tā pati `formAction` tiek izpildīta klienta pusē. Tā vietā, lai notiktu pilnas lapas pārlāde, tā darbojas kā tipisks fetch pieprasījums. Darbība tiek izsaukta, stāvoklis tiek atjaunināts, un tiek atkārtoti renderētas tikai nepieciešamās komponenta daļas.
Tas nozīmē, ka jūs rakstāt savu formas loģiku vienreiz, un tā darbojas nevainojami abos scenārijos. Jūs pēc noklusējuma veidojat noturīgu, pieejamu lietojumprogrammu, kas ir milzīgs ieguvums lietotāja pieredzei visā pasaulē.
Padziļināti modeļi un pielietojuma gadījumi
1. Servera darbības pret klienta darbībām
Jūsu `actionFn`, ko padodat useActionState, var būt standarta klienta puses asinhronā funkcija (kā mūsu piemēros) vai servera darbība (Server Action). Servera darbība ir funkcija, kas definēta serverī un kuru var tieši izsaukt no klienta komponentiem. Tādos ietvaros kā Next.js, jūs to definējat, pievienojot "use server";
direktīvu funkcijas ķermeņa augšpusē.
- Klienta darbības: Ideāli piemērotas mutācijām, kas ietekmē tikai klienta puses stāvokli vai izsauc trešo pušu API tieši no klienta.
- Servera darbības: Perfekti piemērotas mutācijām, kas saistītas ar datubāzi vai citiem servera puses resursiem. Tās vienkāršo jūsu arhitektūru, novēršot nepieciešamību manuāli izveidot API galapunktus katrai mutācijai.
Skaistums ir tajā, ka useActionState darbojas identiski ar abām. Jūs varat aizstāt klienta darbību ar servera darbību, nemainot komponenta kodu.
2. Optimistiskie atjauninājumi ar `useOptimistic`
Lai iegūtu vēl atsaucīgāku sajūtu, jūs varat apvienot useActionState ar useOptimistic āķi. Optimistisks atjauninājums ir tad, kad jūs nekavējoties atjauninat UI, *pieņemot*, ka asinhronā darbība būs veiksmīga. Ja tā neizdodas, jūs atgriežat UI iepriekšējā stāvoklī.
Iedomājieties sociālo mediju lietotni, kurā jūs pievienojat komentāru. Optimistiski jūs uzreiz parādītu jauno komentāru sarakstā, kamēr pieprasījums tiek sūtīts uz serveri. useOptimistic ir izstrādāts, lai strādātu roku rokā ar darbībām, padarot šo modeli viegli implementējamu.
3. Formas atiestatīšana pēc veiksmīgas darbības
Bieži sastopama prasība ir notīrīt formas ievades laukus pēc veiksmīgas iesniegšanas. Ir vairāki veidi, kā to panākt ar useActionState.
- Atslēgas (Key) īpašības triks: Kā parādīts mūsu `CompleteProductForm` piemērā, jūs varat piešķirt unikālu `key` ievades laukam vai visai formai. Kad atslēga mainās, React atvienos veco komponentu un pievienos jaunu, efektīvi atiestatot tā stāvokli. Atslēgas piesaistīšana veiksmes karogam (`key={state.success ? 'success' : 'initial'}`) ir vienkārša un efektīva metode.
- Kontrolētie komponenti: Ja nepieciešams, joprojām varat izmantot kontrolētos komponentus. Pārvaldot ievades vērtību ar useState, jūs varat izsaukt iestatīšanas funkciju, lai to notīrītu useEffect iekšienē, kas klausās veiksmes stāvokli no useActionState.
Biežākās kļūdas un labākā prakse
useFormStatus
novietojums: Atcerieties, ka komponentam, kas izsauc useFormStatus, ir jābūt renderētam kā `<form>` bērnam. Tas nedarbosies, ja tas ir blakus vai vecāks.- Serializējams stāvoklis: Izmantojot servera darbības, stāvokļa objektam, ko atgriež jūsu darbība, jābūt serializējamam. Tas nozīmē, ka tas nevar saturēt funkcijas, simbolus vai citas neserializējamas vērtības. Pieturieties pie vienkāršiem objektiem, masīviem, virknēm, skaitļiem un Būla vērtībām.
- Nemetiet kļūdas (throw) darbībās: Tā vietā, lai izmantotu `throw new Error()`, jūsu darbības funkcijai ir eleganti jāapstrādā kļūdas un jāatgriež stāvokļa objekts, kas apraksta kļūdu (piemēram, `{ success: false, message: 'Notika kļūda' }`). Tas nodrošina, ka stāvoklis vienmēr tiek atjaunināts paredzami.
- Definējiet skaidru stāvokļa formu: No paša sākuma izveidojiet konsekventu stāvokļa objekta struktūru. Forma, piemēram, `{ data: T | null, message: string | null, success: boolean, errors: Record
| null }` var aptvert daudzus lietošanas gadījumus.
useActionState pret useReducer: Ātrs salīdzinājums
No pirmā acu uzmetiena useActionState varētu šķist līdzīgs useReducer, jo abi ir saistīti ar stāvokļa atjaunināšanu, pamatojoties uz iepriekšējo stāvokli. Tomēr tie kalpo atšķirīgiem mērķiem.
useReducer
ir universāls āķis sarežģītu stāvokļa pāreju pārvaldībai klienta pusē. To iedarbina, nosūtot darbības (dispatching actions), un tas ir ideāli piemērots stāvokļa loģikai ar daudzām iespējamām, sinhronām stāvokļa izmaiņām (piemēram, sarežģītam vairāku soļu vednim).useActionState
ir specializēts āķis, kas paredzēts stāvoklim, kas mainās, reaģējot uz vienu, parasti asinhronu darbību. Tā galvenā loma ir integrēties ar HTML formām, servera darbībām un React vienlaicīgās renderēšanas funkcijām, piemēram, gaidīšanas stāvokļa pārejām.
Secinājums: Formu iesniegšanai un ar formām saistītām asinhronām operācijām useActionState ir moderns, mērķtiecīgi izveidots rīks. Citām sarežģītām, klienta puses stāvokļa mašīnām useReducer joprojām ir lieliska izvēle.
Noslēgums: React formu nākotnes pieņemšana
useActionState āķis ir vairāk nekā tikai jauna API; tas atspoguļo fundamentālu pāreju uz robustāku, deklaratīvāku un uz lietotāju orientētu veidu, kā apstrādāt formas un datu mutācijas React. To pieņemot, jūs iegūstat:
- Samazināts liekais kods: Viens āķis aizstāj vairākus useState izsaukumus un manuālu stāvokļa orķestrēšanu.
- Integrēti gaidīšanas stāvokļi: Nemanāmi apstrādājiet ielādes UI ar pavadošo useFormStatus āķi.
- Iebūvēta progresīvā uzlabošana: Rakstiet kodu, kas darbojas ar vai bez JavaScript, nodrošinot pieejamību un noturību visiem lietotājiem.
- Vienkāršota servera komunikācija: Dabiski sader ar servera darbībām, racionalizējot pilna cikla (full-stack) izstrādes pieredzi.
Sākot jaunus projektus vai pārveidojot esošos, apsveriet iespēju izmantot useActionState. Tas ne tikai uzlabos jūsu izstrādātāja pieredzi, padarot kodu tīrāku un paredzamāku, bet arī dos jums iespēju veidot augstākas kvalitātes lietojumprogrammas, kas ir ātrākas, noturīgākas un pieejamas daudzveidīgai globālai auditorijai.