Avastage Reacti useFormState hook serveripoolseks vormide valideerimiseks ja olekuhalduseks. Õppige praktiliste näidete abil looma robustseid, progressiivselt täiustatud vorme.
Reacti useFormState: SĂĽvitsiminek kaasaegsesse vormide olekuhaldusesse ja valideerimisse
Vormid on veebi interaktiivsuse nurgakivi. Alates lihtsatest kontaktivormidest kuni keerukate mitmeastmeliste viisarditeni on need kasutaja sisendi ja andmete edastamise jaoks hädavajalikud. Aastaid on Reacti arendajad navigeerinud olekuhalduse strateegiate maastikul, alates kontrollitud komponentide käsitsi haldamisest useState'iga kuni võimsate kolmandate osapoolte teekide, nagu Formik ja React Hook Form, kasutamiseni. Kuigi need lahendused on suurepärased, on Reacti tuumikmeeskond tutvustanud uut, võimsat primitiivi, mis mõtestab ümber vormide ja serveri vahelise seose: useFormState hook'i.
See hook, mis toodi turule koos React Server Actions'iga, ei ole lihtsalt järjekordne olekuhalduse tööriist. See on fundamentaalne osa integreeritumast, serverikesksest arhitektuurist, mis seab esikohale robustsuse, kasutajakogemuse ja kontseptsiooni, millest sageli räägitakse, kuid mida on keeruline rakendada: progressiivne täiustamine.
Selles põhjalikus juhendis uurime useFormState'i igat tahku. Alustame põhitõdedest, võrdleme seda traditsiooniliste meetoditega, loome praktilisi näiteid ja süveneme valideerimise ja kasutajate tagasiside täiustatud mustritesse. Lõpuks ei mõista te mitte ainult seda, kuidas seda hook'i kasutada, vaid ka paradigma nihet, mida see esindab vormide loomisel kaasaegsetes Reacti rakendustes.
Mis on `useFormState` ja miks see on oluline?
Oma olemuselt on useFormState Reacti hook, mis on loodud vormi oleku haldamiseks vormi toimingu tulemuse põhjal. See võib tunduda lihtne, kuid selle tõeline jõud peitub disainis, mis integreerib sujuvalt kliendipoolsed uuendused serveripoolse loogikaga.
Mõelge tüüpilisele vormi esitamise voole:
- Kasutaja täidab vormi.
- Kasutaja klõpsab "Esita".
- Klient saadab andmed serveri API otspunkti.
- Server töötleb andmeid, valideerib need ja teostab toimingu (nt salvestab andmebaasi).
- Server saadab vastuse tagasi (nt eduteate või valideerimisvigade loendi).
- Kliendipoolne kood peab selle vastuse parssima ja kasutajaliidest vastavalt uuendama.
Traditsiooniliselt nõudis see laadimisolekute, veaolekute ja eduolekute käsitsi haldamist. useFormState sujuvdab kogu seda protsessi, eriti kui seda kasutatakse koos Server Actions'iga raamistikes nagu Next.js. See loob otsese, deklaratiivse seose vormi esitamise ja selle tekitatud oleku vahel.
Kõige olulisem eelis on progressiivne täiustamine. Vorm, mis on ehitatud useFormState'i ja serveri toiminguga, töötab suurepäraselt isegi siis, kui JavaScript on keelatud. Brauser teostab täieliku lehe uuesti laadimise, serveri toiming käivitub ja server renderdab järgmise lehe koos tulemuseks oleva olekuga (nt kuvatakse valideerimisvead). Kui JavaScript on lubatud, võtab React üle, takistab täielikku lehe uuesti laadimist ja pakub sujuvat ühe lehe rakenduse (SPA) kogemust. Saate ühe koodibaasiga mõlema maailma parimad omadused.
Põhitõdede mõistmine: `useFormState` vs. `useState`
useFormState'i mõistmiseks on kasulik võrrelda seda tuttava useState hook'iga. Kuigi mõlemad haldavad olekut, on nende uuendusmehhanismid ja peamised kasutusjuhud erinevad.
useFormState'i signatuur on:
const [state, formAction] = useFormState(fn, initialState);
Signatuuri lahtiseletus:
fn: Funktsioon, mida kutsutakse välja vormi esitamisel. Tavaliselt on see serveri toiming. See saab kaks argumenti: eelmine olek ja vormi andmed. Selle tagastusväärtusest saab uus olek.initialState: Väärtus, mida soovite, et olekul oleks algselt, enne kui vormi kunagi esitatakse.state: Vormi praegune olek. Esialgsel renderdamisel on seeinitialState. Pärast vormi esitamist saab sellest teie toimingufunktsioonifntagastusväärtus.formAction: Uus toiming, mille te edastate oma<form>elemendiactionatribuudile. Kui see toiming käivitatakse (vormi esitamisel), kutsub see välja teie algse funktsioonifnja uuendab olekut.
Kontseptuaalne võrdlus
Kujutage ette lihtsat loendurit.
useState'iga haldate uuendust ise:
const [count, setCount] = useState(0);
function handleIncrement() {
setCount(c => c + 1);
}
Siin on handleIncrement sündmuste käsitleja, mis kutsub selgesõnaliselt välja oleku määraja.
useFormState'iga on oleku uuendus toimingu tulemus:
// See on lihtsustatud, mitte-serveri toimingu näide illustreerimiseks
function incrementAction(previousState, formData) {
// formData sisaldaks esitamisandmeid, kui see oleks päris vorm
return previousState + 1;
}
const [count, dispatchIncrement] = useFormState(incrementAction, 0);
// Kasutaksite `dispatchIncrement` vormi action atribuudis.
Peamine erinevus on see, et useFormState on loodud asünkroonse, tulemuspõhise oleku uuendamise voo jaoks, mis on täpselt see, mis juhtub vormi esitamisel serverile. Te ei kutsu välja `setState` funktsiooni; te käivitate toimingu ja hook uuendab olekut toimingu tagastusväärtusega.
Praktiline rakendamine: esimese vormi loomine `useFormState`'iga
Liigume teooriast praktikasse. Ehitame lihtsa uudiskirjaga liitumise vormi, mis demonstreerib useFormState'i põhifunktsionaalsust. See näide eeldab seadistust raamistikuga, mis toetab React Server Actions'it, nagu Next.js koos App Routeriga.
1. samm: Määratlege serveri toiming
Serveri toiming on funktsioon, mille saate märkida direktiiviga 'use server';. See võimaldab funktsiooni turvaliselt serveris käivitada, isegi kui seda kutsutakse kliendi komponendist. See on ideaalne partner useFormState'ile.
Loome faili, näiteks app/actions.js:
'use server';
// See on lihtsustatud toiming. Päris rakenduses valideeriksite e-posti
// ja salvestaksite selle andmebaasi või kolmanda osapoole teenusesse.
export async function subscribeToNewsletter(previousState, formData) {
const email = formData.get('email');
// Põhiline serveripoolne valideerimine
if (!email || !email.includes('@')) {
return {
message: 'Palun sisestage kehtiv e-posti aadress.',
success: false
};
}
console.log(`Uus tellija: ${email}`);
// Simuleerime andmebaasi salvestamist
await new Promise(res => setTimeout(res, 1000));
return {
message: 'Täname tellimuse eest!',
success: true
};
}
Pange tähele funktsiooni signatuuri: (previousState, formData). See on nõutav funktsioonide puhul, mida kasutatakse koos useFormState'iga. Kontrollime e-posti ja tagastame struktureeritud objekti, millest saab meie komponendi uus olek.
2. samm: Looge vormi komponent
NĂĽĂĽd loome kliendipoolse komponendi, mis seda toimingut kasutab.
'use client';
import { useFormState } from 'react-dom';
import { subscribeToNewsletter } from './actions';
const initialState = {
message: null,
success: false,
};
export function NewsletterForm() {
const [state, formAction] = useFormState(subscribeToNewsletter, initialState);
return (
<div>
<h3>Liitu meie uudiskirjaga</h3>
<form action={formAction}>
<label htmlFor="email">E-posti aadress:</label>
<input type="email" id="email" name="email" required />
<button type="submit">Telli</button>
</form>
{state.message && (
<p style={{ color: state.success ? 'green' : 'red' }}>
{state.message}
</p>
)}
</div>
);
}
Komponendi lahkamine:
- Impordime
useFormStateteegistreact-dom. See on oluline — see ei asu põhilisesreactpaketis. - Määratleme
initialStateobjekti. See tagab, et meiestatemuutuja on esimesel renderdamisel korrektselt defineeritud. - Kutsume välja
useFormState(subscribeToNewsletter, initialState), et saada omastateja mähitudformAction. - Edastame selle
formAction'i otse<form>elemendiactionatribuudile. See on maagiline ühendus. - Renderdame tingimuslikult teate, mis põhineb
state.message'il, kujundades selle erinevalt edu ja vea korral.
Nüüd, kui kasutaja vormi esitab, juhtub järgmine:
- React pĂĽĂĽab esitamise kinni.
- See käivitab
subscribeToNewsletterserveri toimingu praeguse oleku ja vormi andmetega. - Serveri toiming käivitub, teostab oma loogika ja tagastab uue olekuobjekti.
useFormStatesaab selle uue objekti ja käivitabNewsletterFormkomponendi uuesti renderdamise uuendatudstate'iga.- Edu- või veateade ilmub vormi alla ilma täieliku lehe uuesti laadimiseta.
Täiustatud vormide valideerimine `useFormState`'iga
Eelmine näide näitas lihtsat teadet. useFormState'i tõeline jõud avaldub keeruliste, väljaspetsiifiliste valideerimisvigade käsitlemisel, mis tagastatakse serverist.
1. samm: Täiustage serveri toimingut üksikasjalike vigade jaoks
Loome robustsema registreerimisvormi toimingu. See valideerib kasutajanime, e-posti ja parooli, tagastades vigade objekti, kus võtmed vastavad väljade nimedele.
Failis app/actions.js:
'use server';
export async function registerUser(previousState, formData) {
const username = formData.get('username');
const email = formData.get('email');
const password = formData.get('password');
const errors = {};
if (!username || username.length < 3) {
errors.username = 'Kasutajanimi peab olema vähemalt 3 tähemärki pikk.';
}
if (!email || !email.includes('@')) {
errors.email = 'Palun sisestage kehtiv e-posti aadress.';
} else if (await isEmailTaken(email)) { // Simuleerime andmebaasi kontrolli
errors.email = 'See e-post on juba registreeritud.';
}
if (!password || password.length < 8) {
errors.password = 'Parool peab olema vähemalt 8 tähemärki pikk.';
}
if (Object.keys(errors).length > 0) {
return { errors };
}
// Jätkake kasutaja registreerimisega...
console.log('Registreerin kasutajat:', { username, email });
return { message: 'Registreerimine õnnestus! Palun kontrollige oma e-posti kinnitamiseks.' };
}
// Abifunktsioon andmebaasi otsingu simuleerimiseks
async function isEmailTaken(email) {
if (email === 'test@example.com') {
return true;
}
return false;
}
Meie toiming tagastab nüüd olekuobjekti, millel võib olla üks kahest kujust: { errors: { ... } } või { message: '...' }.
2. samm: Looge vorm väljaspetsiifiliste vigade kuvamiseks
Kliendi komponent peab nüüd lugema seda struktureeritud veaobjekti ja kuvama teated asjakohaste sisendite kõrval.
'use client';
import { useFormState } from 'react-dom';
import { registerUser } from './actions';
const initialState = {
message: null,
errors: {},
};
export function RegistrationForm() {
const [state, formAction] = useFormState(registerUser, initialState);
return (
<form action={formAction}>
<h2>Loo konto</h2>
{state?.message && <p className="success-message">{state.message}</p>}
<div className="form-group">
<label htmlFor="username">Kasutajanimi</label>
<input id="username" name="username" aria-describedby="username-error" />
{state?.errors?.username && (
<p id="username-error" className="error-message">{state.errors.username}</p>
)}
</div>
<div className="form-group">
<label htmlFor="email">E-post</label>
<input id="email" name="email" type="email" aria-describedby="email-error" />
{state?.errors?.email && (
<p id="email-error" className="error-message">{state.errors.email}</p>
)}
</div>
<div className="form-group">
<label htmlFor="password">Parool</label>
<input id="password" name="password" type="password" aria-describedby="password-error" />
{state?.errors?.password && (
<p id="password-error" className="error-message">{state.errors.password}</p>
)}
</div>
<button type="submit">Registreeri</button>
</form>
);
}
Märkus ligipääsetavuse kohta: Kasutame sisendil atribuuti aria-describedby, mis viitab veateate konteineri ID-le. See on ekraanilugeja kasutajate jaoks ülioluline, kuna see seob programmiliseelt sisendivälja selle konkreetse valideerimisveaga.
Kombineerimine kliendipoolse valideerimisega
Serveripoolne valideerimine on tõe allikas, kuid serveri edasi-tagasi ringi ootamine, et öelda kasutajale, et ta unustas oma e-posti aadressist '@' märgi, on halb kogemus. useFormState ei asenda kliendipoolset valideerimist; see täiendab seda suurepäraselt.
Saate lisada standardseid HTML5 valideerimisatribuute koheseks tagasisideks:
<input
id="username"
name="username"
required
minLength="3"
aria-describedby="username-error"
/>
<input
id="email"
name="email"
type="email"
required
aria-describedby="email-error"
/>
Sellega takistab brauser vormi esitamist, kui need põhilised kliendipoolsed reeglid ei ole täidetud. useFormState'i voog käivitub ainult kehtivate kliendipoolsete andmete puhul, kus see teostab keerukamaid, turvalisi serveripoolseid kontrolle (näiteks kas e-post on juba kasutusel).
Ootel kasutajaliidese olekute haldamine `useFormStatus`'iga
Vormi esitamisel on viivitus, kuni serveri toimingut täidetakse. Hea kasutajakogemus hõlmab selle aja jooksul tagasiside andmist, näiteks esitamisnupu keelamist ja laadimisindikaatori kuvamist.
React pakub täpselt selleks otstarbeks kaaslase hook'i: useFormStatus.
useFormStatus hook annab olekuteavet viimase vormi esitamise kohta. Oluline on see, et see peab olema renderdatud <form> komponendi sees, mille olekut soovite jälgida.
Nutika esitamisnupu loomine
Hea tava on luua oma esitamisnupu jaoks eraldi komponent, mis seda hook'i kasutab.
'use client';
import { useFormStatus } from 'react-dom';
export function SubmitButton() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Esitan...' : 'Registreeri'}
</button>
);
}
NĂĽĂĽd saame selle SubmitButton'i importida ja kasutada meie RegistrationForm'is:
// ... RegistrationForm komponendi sees
import { SubmitButton } from './SubmitButton';
// ...
<SubmitButton />
</form>
// ...
Kui kasutaja klõpsab nuppu, juhtub järgmine:
- Vormi esitamine algab.
useFormStatushookSubmitButton'i sees teatabpending: true.SubmitButtonkomponent renderdatakse uuesti. Nupp muutub keelatuks ja selle tekst muutub "Esitan...".- Kui serveri toiming on lõpule viidud ja
useFormStateuuendab olekut, ei ole vorm enam ootel. useFormStatusteatabpending: falseja nupp naaseb oma tavapärasesse olekusse.
See lihtne muster parandab drastiliselt kasutajakogemust, pakkudes selget ja kohest tagasisidet vormi oleku kohta.
Parimad tavad ja levinumad lõksud
useFormState'i oma projektidesse integreerimisel pidage meeles neid juhiseid, et vältida levinud probleeme.
Mida teha
- Pakkuge hästi defineeritud
initialState. See väldib vigu esialgsel renderdamisel, kui teie oleku omadused (naguerrors) võivad olla defineerimata. - Hoidke oma oleku kuju järjepidevana. Tagastage oma toimingust alati sama võtmetega objekt (nt
message,errors), isegi kui nende väärtused on nullid või tühjad. See muudab teie kliendipoolse renderdamise loogika lihtsamaks. - Kasutage
useFormStatus't kasutajakogemuse tagasisideks. Keelatud nupp esitamise ajal on professionaalse kasutajakogemuse jaoks kohustuslik. - Eelistage ligipääsetavust. Kasutage
labelsilte ja ühendage veateated sisenditegaaria-describedbyabil. - Tagastage uusi olekuobjekte. Oma serveri toimingus tagastage alati uus objekt. Ärge muteerige
previousStateargumenti.
Mida mitte teha
- Ärge unustage esimest argumenti. Teie toimingufunktsioon peab aktsepteerima
previousState'i oma esimese argumendina, isegi kui te seda ei kasuta. - Ärge kutsuge
useFormStatus't välja väljaspool<form>'i. See ei tööta. See peab olema jälgitava vormi järeltulija. - Ärge loobuge kliendipoolsest valideerimisest. Kasutage HTML5 atribuute või kerget teeki kohese tagasiside saamiseks lihtsate piirangute kohta. Toetuge serverile äriloogika ja turvalisuse valideerimiseks.
- Ärge pange tundlikku loogikat vormi komponenti. Selle mustri ilu seisneb selles, et kogu teie kriitiline valideerimise ja andmetöötluse loogika elab turvaliselt serveris toimingu sees.
Millal valida `useFormState` teiste teekide asemel
Reactil on rikkalik vormiteekide ökosüsteem. Millal peaksite siis valima sisseehitatud useFormState'i versus teegi nagu React Hook Form või Formik?
Valige `useFormState`, kui:
- Kasutate kaasaegset, serverikeskset raamistikku. See on loodud töötama koos Server Actions'iga raamistikes nagu Next.js (App Router), Remix jne.
- Progressiivne täiustamine on prioriteet. Kui teil on vaja, et teie vormid töötaksid ilma JavaScriptita, on see parim sisseehitatud lahendus.
- Teie valideerimine sõltub suuresti serverist. Vormide puhul, kus kõige olulisemad valideerimisreeglid nõuavad andmebaasi otsinguid või keerulist äriloogikat, on
useFormStateloomulik valik. - Soovite minimeerida kliendipoolset JavaScripti. See muster laadib olekuhalduse ja valideerimisloogika serverisse, mille tulemuseks on kergem kliendi pakett.
Kaaluge teisi teeke (nagu React Hook Form), kui:
- Ehitad traditsioonilist SPA-d. Kui teie rakendus on kliendipoolselt renderdatud (CSR) rakendus, mis suhtleb REST või GraphQL API-dega, on spetsiaalne kliendipoolne teek sageli ergonoomilisem.
- Vajate väga keerulist, puhtalt kliendipoolset interaktiivsust. Funktsioonide jaoks nagu keerukas reaalajas valideerimine, mitmeastmelised viisardid jagatud kliendi olekuga, dünaamilised väljade massiivid või keerulised andmete teisendused enne esitamist, pakuvad küpsed teegid rohkem valmislahendusi.
- Jõudlus on kriitiline väga suurte vormide puhul. Teegid nagu React Hook Form on optimeeritud, et minimeerida uuesti renderdamisi kliendi poolel, mis võib olla kasulik kümnete või sadade väljadega vormide puhul.
Valik ei ole vastastikku välistav. Suures rakenduses võite kasutada useFormState'i lihtsate serveriga seotud vormide jaoks (nagu kontakti- või registreerimisvormid) ja täisfunktsionaalset teeki keeruka seadete armatuurlaua jaoks, mis on puhtalt kliendipoolselt interaktiivne.
Kokkuvõte: vormide tulevik Reactis
useFormState hook on midagi enamat kui lihtsalt uus API; see peegeldab Reacti arenevat filosoofiat. Vormi oleku tihedal integreerimisel serveripoolsete toimingutega ületab see kliendi-serveri lõhe viisil, mis tundub nii võimas kui ka lihtne.
Seda hook'i kasutades saate kolm kriitilist eelist:
- Lihtsustatud olekuhaldus: Kõrvaldate käsitsi andmete toomise, laadimisolekute haldamise ja serveri vastuste parssimise tüütu koodi.
- Vastupidavus vaikimisi: Progressiivne täiustamine on sisse ehitatud, tagades, et teie vormid on ligipääsetavad ja funktsionaalsed kõigile kasutajatele, olenemata nende seadmest või võrgutingimustest.
- Selge vastutusalade eraldamine: Kasutajaliidese loogika jääb teie kliendi komponentidesse, samas kui äri- ja valideerimisloogika on turvaliselt serveris kaasas.
Kuna Reacti ökosüsteem jätkab serverikesksete mustrite omaksvõtmist, on useFormState'i ja selle kaaslase useFormStatus'i valdamine oluline oskus arendajatele, kes soovivad luua kaasaegseid, vastupidavaid ja kasutajasõbralikke veebirakendusi. See julgustab meid ehitama veebi jaoks nii, nagu see oli mõeldud – vastupidavaks ja ligipääsetavaks –, pakkudes samal ajal rikkalikke ja interaktiivseid kogemusi, mida kasutajad on harjunud ootama.