Å opprette delstatene globalt kan redusere appens ytelse. Lær hvordan du effektivt kan opprette og bruke tilstander i React-applikasjonen din.

Hvis du har skrevet mye React-kode, er sjansen stor for at du har brukt tilstanden feil. En vanlig feil mange React-utviklere gjør er å lagre tilstander globalt i applikasjonen, i stedet for å lagre dem i komponentene der de brukes.

Finn ut hvordan du kan refaktorisere koden din for å bruke lokal stat og hvorfor det alltid er en god idé å gjøre det.

Grunnleggende eksempel på tilstand i React

Her er en veldig enkel tellesøknad som eksemplifiserer hvordan staten vanligvis håndteres i React:

import {useState} fra'reagere'
import {Disk} fra'disk'

funksjonApp(){
konst [count, setCount] = useState(0)
komme tilbake<Disktelle={telle}setCount={setCount} />
}

eksportmisligholde App

På linje 1 og 2 importerer du useState() krok for å skape staten, og den Disk komponent. Du definerer telle stat og setCount metode for å oppdatere staten. Deretter passerer du begge ned til Disk komponent.

De Disk komponenten gjengir deretter telle og samtaler setCount å øke og redusere tellingen.

funksjonDisk({count, setCount}) {
komme tilbake (

Du definerte ikke telle variabel og setCount fungere lokalt inne i Disk komponent. I stedet sendte du det inn fra den overordnede komponenten (App). Med andre ord, du bruker en global stat.

Problemet med globale stater

Problemet med å bruke en global tilstand er at du lagrer tilstanden i en overordnet komponent (eller forelder til en forelder) og deretter gir det ned som rekvisitter til komponenten der den tilstanden faktisk er nødvendig.

Noen ganger er dette greit når du har en tilstand som er delt på tvers av mange komponenter. Men i dette tilfellet bryr ingen annen komponent seg om telle stat bortsett fra Disk komponent. Derfor er det bedre å flytte staten til Disk komponent der den faktisk brukes.

Flytte staten til barnekomponenten

Når du flytter staten til Disk komponent, vil det se slik ut:

import {useState} fra'reagere'

funksjonDisk() {
konst [count, setCount] = useState(0)
komme tilbake (


Så inne i din App komponent, trenger du ikke sende noe ned til Disk komponent:

// importerer
funksjonApp(){
komme tilbake<Disk />
}

Telleren vil fungere nøyaktig det samme som den gjorde før, men den store forskjellen er at alle delstatene dine er lokalt inne i denne Disk komponent. Så hvis du trenger å ha en annen teller på hjemmesiden, vil du ha to uavhengige tellere. Hver disk er selvforsynt og tar seg av hele sin egen tilstand.

Håndteringstilstand i mer komplekse applikasjoner

En annen situasjon der du vil bruke en global stat er med skjemaer. De App komponenten nedenfor sender skjemadataene (e-post og passord) og setter-metoden ned til Innloggingsskjema komponent.

import { useState } fra"reagere";
import { Innloggingsskjema } fra"./Innloggingsskjema";

funksjonApp() {
konst [formData, setFormData] = useState({
e-post: "",
passord: "",
});

funksjonoppdater FormData(nye Data) {
setFormData((forrige) => {
komme tilbake { ...prev, ...newData };
});
}

funksjonved innsending() {
konsoll.log (formData);
}

komme tilbake (
data={formData}
updateData={updateFormData}
onSubmit={onSubmit}
/>
);
}

De Innloggingsskjema komponenten tar inn påloggingsinformasjonen og gjengir den. Når du sender inn skjemaet, kalles det oppdater Data funksjon som også overføres fra den overordnede komponenten.

funksjonInnloggingsskjema({ onSubmit, data, updateData }) {
funksjonhandleSend inn(e) {
e.preventDefault();
onSubmit();
}

komme tilbake (


I stedet for å administrere staten på den overordnede komponenten, er det bedre å flytte staten til LoginForm.js, som er der du skal bruke koden. Hvis du gjør det, blir hver komponent selvstendig og ikke avhengig av en annen komponent (dvs. overordnet) for data. Her er den modifiserte versjonen av Innloggingsskjema:

import { useRef } fra"reagere";

funksjonInnloggingsskjema({ onSubmit }) {
konst emailRef = brukRef();
konst passordRef = brukRef();

funksjonhandleSend inn(e) {
e.preventDefault();
onSubmit({
e-post: emailRef.current.value,
passord: passordRef.current.value,
});
}

komme tilbake (


Her binder du input til en variabel ved hjelp av ref attributter og brukRef React hook, i stedet for å sende oppdateringsmetodene direkte. Dette hjelper deg med å fjerne detaljert kode og optimer formytelsen ved å bruke useRef-kroken.

I den overordnede komponenten (App.js), kan du fjerne både den globale staten og updateFormData() metode fordi du ikke lenger trenger den. Den eneste funksjonen som er igjen er onSubmit(), som du påkaller fra innsiden av Innloggingsskjema komponent for å logge påloggingsdetaljene på konsollen.

funksjonApp() {
funksjonved innsending(formData) {
konsoll.log (formData);
}

komme tilbake (
data={formData}
updateData={updateFormData}
onSubmit={onSubmit}
/>
);
}

Ikke bare gjorde du staten din så lokal som mulig, men du fjernet faktisk behovet for enhver stat i det hele tatt (og brukte refs i stedet). Så din App komponenten har blitt betydelig enklere (med bare én funksjon).

Din Innloggingsskjema komponenten ble også enklere fordi du ikke trengte å bekymre deg for å oppdatere tilstanden. I stedet holder du bare styr på to refs, og det er det.

Håndtering av delt tilstand

Det er ett problem med tilnærmingen om å prøve å gjøre staten så lokal som mulig. Du vil ofte støte på scenarier der den overordnede komponenten ikke bruker tilstanden, men den overfører den til flere komponenter.

Et eksempel er å ha en TodoContainer overordnet komponent med to underordnede komponenter: Gjøremålsliste og TodoCount.

funksjonTodoContainer() {
konst [todos, setTodos] = useState([])

komme tilbake (
<>


</>
)
}

Begge disse barnekomponentene krever todos stat, altså TodoContainer gir det til begge. I scenarier som disse må man gjøre staten så lokal som mulig. I eksemplet ovenfor, å sette den inne i TodosContainer er så lokal som du kan bli.

Hvis du skulle sette denne tilstanden i din App komponent, ville den ikke være så lokal som mulig fordi den ikke er den nærmeste forelderen til de to komponentene som trenger dataene.

For store applikasjoner, administrere staten bare med useState() krok kan vise seg å være vanskelig. I slike tilfeller må du kanskje velge React Context API eller Reager Redux for å effektivt styre staten.

Lær mer om React Hooks

Kroker danner grunnlaget for React. Ved å bruke kroker i React kan du unngå å skrive lang kode som ellers ville brukt klasser. useState()-kroken er uten tvil den mest brukte React-kroken, men det er mange andre som useEffect(), useRef() og useContext().

Hvis du ønsker å bli dyktig til å utvikle applikasjoner med React, må du vite hvordan du bruker disse krokene i applikasjonen din.