Oprettelse af stater globalt kan sænke din apps ydeevne. Lær, hvordan du effektivt kan oprette og bruge tilstande i din React-applikation.

Hvis du har skrevet meget React-kode, er chancerne for, at du har brugt tilstanden forkert. En almindelig fejl, som mange React-udviklere gør, er at gemme tilstande globalt i applikationen, i stedet for at gemme dem i de komponenter, hvor de bruges.

Lær, hvordan du kan refaktorisere din kode for at bruge den lokale stat, og hvorfor det altid er en god idé at gøre det.

Grundlæggende eksempel på tilstand i React

Her er en meget simpel modansøgning der eksemplificerer, hvordan staten typisk håndteres i React:

importere {useState} fra'reagere'
importere {Tæller} fra'tæller'

fungereApp(){
konst [count, setCount] = useState(0)
Vend tilbage<Tællertælle={tælle}setCount={setCount} />
}

eksportStandard App

På linje 1 og 2 importerer du useState() krog for at skabe staten, og den Tæller komponent. Du definerer tælle stat og setCount metode til at opdatere staten. Så passerer du begge ned til Tæller komponent.

Det Tæller komponent gengiver derefter tælle og opkald setCount at øge og mindske antallet.

fungereTæller({count, setCount}) {
Vend tilbage (

Du definerede ikke tælle variabel og setCount fungere lokalt inde i Tæller komponent. I stedet sendte du det ind fra den overordnede komponent (App). Med andre ord, du bruger en global stat.

Problemet med globale stater

Problemet med at bruge en global tilstand er, at du gemmer tilstanden i en overordnet komponent (eller forælder til en forælder) og derefter videregive det som rekvisitter til den komponent, hvor denne tilstand faktisk er nødvendig.

Nogle gange er dette fint, når du har en tilstand, der deles på tværs af mange komponenter. Men i dette tilfælde er der ingen anden komponent, der bekymrer sig om tælle stat bortset fra Tæller komponent. Derfor er det bedre at flytte staten til Tæller komponent, hvor den rent faktisk bruges.

Flytning af staten til børnekomponenten

Når du flytter staten til Tæller komponent, ville det se sådan ud:

importere {useState} fra'reagere'

fungereTæller() {
konst [count, setCount] = useState(0)
Vend tilbage (


Så inde i din App komponent, behøver du ikke at videregive noget til Tæller komponent:

// importerer
fungereApp(){
Vend tilbage<Tæller />
}

Tælleren vil fungere nøjagtigt det samme, som den gjorde før, men den store forskel er, at alle dine stater er lokalt inde i denne Tæller komponent. Så hvis du skal have endnu en tæller på hjemmesiden, så har du to uafhængige tællere. Hver tæller er selvstændig og tager sig af hele sin egen tilstand.

Håndteringstilstand i mere komplekse applikationer

En anden situation, hvor du ville bruge en global stat, er med formularer. Det App komponenten nedenfor sender formulardataene (e-mail og adgangskode) og indstillingsmetoden ned til LoginForm komponent.

importere { useState } fra"reagere";
importere { LoginForm } fra"./LoginForm";

fungereApp() {
konst [formData, setFormData] = useState({
e-mail: "",
adgangskode: "",
});

fungereopdatereFormData(nye Data) {
sætFormData((forrige) => {
Vend tilbage { ...prev, ...newData };
});
}

fungereved indsend() {
konsol.log (formData);
}

Vend tilbage (
data={formData}
updateData={updateFormData}
onSubmit={onSubmit}
/>
);
}

Det LoginForm komponent tager login-oplysningerne ind og gengiver dem. Når du indsender formularen, kalder den opdatere Data funktion, som også videregives fra den overordnede komponent.

fungereLoginForm({ onSubmit, data, updateData }) {
fungerehandleSend(e) {
e.preventDefault();
onSubmit();
}

Vend tilbage (


I stedet for at administrere tilstanden på den overordnede komponent, er det bedre at flytte tilstanden til LoginForm.js, hvor du skal bruge koden. Hvis du gør det, bliver hver komponent selvstændig og ikke afhængig af en anden komponent (dvs. forælderen) for data. Her er den ændrede version af LoginForm:

importere { useRef } fra"reagere";

fungereLoginForm({ onSubmit }) {
konst emailRef = useRef();
konst passwordRef = useRef();

fungerehandleSend(e) {
e.preventDefault();
ved indsend({
e-mail: emailRef.current.value,
adgangskode: passwordRef.current.value,
});
}

Vend tilbage (


Her binder du input til en variabel vha ref egenskaber og brugRef React hook, i stedet for at videregive opdateringsmetoderne direkte. Dette hjælper dig med at fjerne verbose kode og optimer formularydelsen ved hjælp af useRef-krogen.

I den overordnede komponent (App.js), kan du fjerne både den globale tilstand og updateFormData() metode, fordi du ikke længere har brug for den. Den eneste funktion tilbage er onSubmit(), som du påberåber dig inde fra LoginForm komponent for at logge loginoplysningerne på konsollen.

fungereApp() {
fungereved indsend(formData) {
konsol.log (formData);
}

Vend tilbage (
data={formData}
updateData={updateFormData}
onSubmit={onSubmit}
/>
);
}

Ikke alene gjorde du din stat så lokal som muligt, men du fjernede faktisk behovet for enhver stat overhovedet (og brugte refs i stedet). Så din App komponent er blevet betydeligt enklere (med kun én funktion).

Din LoginForm komponent blev også enklere, fordi du ikke behøvede at bekymre dig om at opdatere tilstanden. I stedet holder du bare styr på to refs, og det er det.

Håndtering af delt tilstand

Der er et problem med tilgangen til at forsøge at gøre staten så lokal som muligt. Du vil ofte støde på scenarier, hvor den overordnede komponent ikke bruger tilstanden, men den overfører den til flere komponenter.

Et eksempel er at have en TodoContainer overordnet komponent med to underordnede komponenter: TodoList og TodoCount.

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

Vend tilbage (
<>


</>
)
}

Begge disse underordnede komponenter kræver todos stat, så TodoContainer giver det til dem begge. I scenarier som disse skal du gøre staten så lokal som muligt. I ovenstående eksempel, at sætte den inde i TodosContainer er så lokal, som du kan blive.

Hvis du skulle sætte denne tilstand i din App komponent, ville det ikke være så lokalt som muligt, fordi det ikke er den nærmeste forælder til de to komponenter, der har brug for dataene.

For store applikationer, administrere staten bare med useState() krog kan vise sig at være svært. I sådanne tilfælde skal du muligvis vælge React Context API eller Reager Redux at styre staten effektivt.

Lær mere om React Hooks

Kroge danner grundlaget for React. Ved at bruge hooks i React kan du undgå at skrive lang kode, som ellers ville bruge klasser. useState() hook er uden tvivl den mest brugte React hook, men der er mange andre såsom useEffect(), useRef() og useContext().

Hvis du ønsker at blive dygtig til at udvikle applikationer med React, så skal du vide, hvordan du bruger disse kroge i din applikation.