Komme i gang med Redux Hvorfor Redux?

Når du lærer React, vil du nesten alltid høre folk si hvor flott Redux er, og at du burde prøve. Reaksøkosystemet vokser raskt, og det er så mange biblioteker at du kan koble deg til React, for eksempel flyt, redux, middlewares, mobx, etc. 

Læringsreaktor er enkelt, men å bli vant til hele React-økosystemet tar tid. Denne opplæringen er en introduksjon til en av de integrerte komponentene i React ecosystem-Redux.

Grunnleggende Ikke-Redux Terminologi

Her er noen av de vanlige terminologiene du kanskje ikke er kjent med, men de er ikke spesifikt for Redux per se. Du kan skumme gjennom denne delen og komme tilbake hit når / hvis noe ikke gir mening.  

Ren funksjon

En ren funksjon er bare en normal funksjon med to ytterligere begrensninger som den må tilfredsstille: 

  1. Gitt et sett av innganger, bør funksjonen alltid returnere samme utgang. 
  2. Det gir ingen bivirkninger.

For eksempel, her er en ren funksjon som returnerer summen av to tall.

/ * Ren add-funksjon * / const add = (x, y) => return x + y;  console.log (legg til (2,3)) // 5 

Rene funksjoner gir en forutsigbar utgang og er deterministisk. En funksjon blir uren når den utfører noe annet enn å beregne returverdien. 

For eksempel bruker Add-funksjonen nedenfor en global tilstand for å beregne utdataene. I tillegg logger funksjonen også verdien til konsollen, som anses å være en bivirkning. 

const y = 10; const impureAdd = (x) => console.log ('Inngangene er $ x og $ y'); returnere x + y;  

Observerbare bivirkninger

"Observerbare bivirkninger" er et fint uttrykk for interaksjoner som er gjort av en funksjon med omverdenen. Hvis en funksjon forsøker å skrive en verdi til en variabel som eksisterer utenfor funksjonen eller forsøker å ringe en ekstern metode, kan du trygt kalle disse tingene bivirkninger. 

Men hvis en ren funksjon kaller en annen ren funksjon, kan funksjonen behandles som ren. Her er noen av de vanlige bivirkningene:

  • gjør API-anrop
  • logger på konsoll eller utskriftsdata
  • muterende data
  • DOM manipulasjon
  • henter nåværende tid

Container og presentasjonskomponenter

Å dele komponentarkitekturen i to er nyttig når du arbeider med React-applikasjoner. Du kan i stor grad klassifisere dem i to kategorier: beholderkomponenter og presentasjonskomponenter. De er også populært kjent som smarte og dumme komponenter. 

Beholderkomponenten er opptatt av hvordan ting fungerer, mens presentasjonskomponenter er opptatt av hvordan ting ser ut. For å forstå konseptene bedre har jeg dekket det i en annen opplæring: Container vs Presentational Components i React.

Mutable vs Immutable Objects

Et muterbart objekt kan defineres som følger:

EN mutable objekt er et objekt hvis tilstand kan endres etter at den er opprettet.

Immutability er nøyaktig motsatt - et uforanderlig objekt er et objekt hvis tilstand kan ikke modifiseres etter at den er opprettet. I JavaScript er strenger og numre uforanderlige, men objekter og arrayer er ikke. Eksemplet viser forskjellen bedre. 

/ * Strings og tall er uforanderlige * / la a = 10; la b = a; b = 3; console.log ('a = $ a og b = $ b'); // a = 10 og b = 3 / * Men objekter og arrayer er ikke * / / * La oss starte med objekter * / la bruker = navn: "Bob", alder: 22, jobb: "Ingen" active_user = bruker ; active_user.name = "Tim"; // Begge objektene har samme verdi console.log (active_user); // "navn": "Tim", "alder": 22, "jobb": "Ingen" console.log (bruker); // "navn": "Tim", "alder": 22, "jobb": "Ingen" / * Nå for arrays * / la usersId = [1,2,3,4,5] la usersIdDup = usersId ; usersIdDup.pop (); console.log (usersIdDup); // [1,2,3,4] console.log (usersId); // [1,2,3,4]

For å gjøre objekter uforanderlige, bruk Object.assign Metode for å lage en ny metode eller hele den nye spredningsoperatøren.

la bruker = navn: "Bob", alder: 22, jobb: "Ingen" active_user = Object.assign (, bruker, navn: "Tim") console.log (bruker); // "navn": "Bob", "alder": 22, "jobb": "Ingen" console.log (active_user); //  "name": "Tim", "alder": 22, "jobb": "Ingen" 

Hva er Redux?

Den offisielle siden definerer Redux som følger:

Redux er en forutsigbar tilstandsbeholder for JavaScript-applikasjoner. 

Selv om det beskrives nøyaktig Redux, er det lett å gå seg vill når du ser det større bildet av Redux for første gang. Den har så mange bevegelige stykker som du må passe sammen. Men når du gjør det, lover jeg deg, du vil begynne å elske Redux. 

Redux er et statsadministrasjonsbibliotek som du kan knytte til et hvilket som helst JavaScript-bibliotek, og ikke bare React. Det fungerer imidlertid veldig bra med React på grunn av Reacts funksjonelle natur. For å forstå dette bedre, la oss ta en titt på staten.

Som du kan se, bestemmer en komponents tilstand hva som blir gjengitt og hvordan det oppfører seg. Søknaden har en innledende tilstand, og eventuelle brukerinteraksjoner utløser en handling som oppdaterer staten. Når staten er oppdatert, blir siden gjengitt.

Med React har hver komponent en lokal stat som er tilgjengelig fra komponenten, eller du kan sende dem ned som rekvisitter til barnekomponenter. Vi bruker vanligvis staten til å lagre:

  1. UI-stat og overgangsdata. Dette inkluderer en liste over brukergrensesnittelementer for navigasjonsmenyen eller skjemainnganger i en kontrollert komponent.
  2. Søknadstilstand som data hentet fra en server, brukerens innloggingsstatus osv.

Lagring av applikasjonsdata i en komponents tilstand er greit når du har et grunnleggende React-program med noen få komponenter. 

Komponenthierarki av en grunnleggende applikasjon

Imidlertid vil de fleste virkelige apps ha mange flere funksjoner og komponenter. Når antall nivåer i komponenthierarkiet øker, blir styring av staten problematisk. 

Skisse av en middels stor applikasjon

Hvorfor skal du bruke Redux?

Her er et veldig sannsynlig scenario som du kanskje kommer over når du arbeider med React.

  1. Du bygger en mellomstor applikasjon, og du har komponentene dine delt inn i smarte og dumme komponenter. 
  2. De smarte komponentene håndterer tilstanden og sender dem deretter til de dumme komponentene. De tar seg av å lage API-anrop, henter dataene fra datakilden, behandler dataene, og deretter stiller inn tilstanden. De dumme komponentene mottar rekvisitter og returnerer UI-representasjonen. 
  3. Når du skal skrive en ny komponent, er det ikke alltid klart hvor du skal plassere staten. Du kan la staten være en del av en beholder som er en umiddelbar forelder for presentasjonsdelen. Enda bedre, du kan flytte staten høyere opp i hierarkiet slik at staten er tilgjengelig for flere presentasjonskomponenter.
  4. Når appen vokser, ser du at staten er spredt over alt. Når en komponent trenger tilgang til staten som den ikke umiddelbart har tilgang til, vil du prøve å løfte staten opp til nærmeste komponent forfader. 
  5. Etter konstant refactoring og opprydding slutter du med de fleste statlige plasseringssteder øverst i komponenthierarkiet. 
  6. Til slutt bestemmer du at det er en god ide å la en komponent øverst håndtere staten globalt og deretter sende alt ned. Hver annen komponent kan abonnere på rekvisitter som de trenger og ignorerer resten.

Dette er det jeg personlig har opplevd med React, og mange andre utviklere vil være enige. React er et visningsbibliotek, og det er ikke Reacts jobb å spesifikt administrere tilstand. Det vi leter etter er prinsippet om separasjon av bekymringer. 

Redux hjelper deg å skille applikasjonstilstanden fra React. Redux lager en global butikk som ligger på toppnivå av søknaden din og feeds staten til alle andre komponenter. I motsetning til Flux har Redux ikke flere butikkobjekter. Hele tilstanden til søknaden er innenfor det aktuelle butikkobjektet, og du kan potensielt bytte visningslaget med et annet bibliotek med butikken intakt.

Komponentene gjengis hver gang butikken er oppdatert, med svært lite innvirkning på ytelsen. Det er gode nyheter, og dette gir mange fordeler med det. Du kan behandle alle React-komponentene dine som dumme, og React kan bare fokusere på utsikten over ting.

Nå som vi vet hvorfor Redux er nyttig, la oss dykke inn i Redux-arkitekturen.

Redux-arkitekturen

Når du lærer Redux, er det noen kjernekonsepter som du trenger å bli vant til. Bildet nedenfor beskriver Redux-arkitekturen og hvordan alt er koblet sammen. 

Redux i et nøtteskall

Hvis du er vant til Flux, kan noen av elementene bli kjent. Hvis ikke, det er ok, for vi skal dekke alt fra basen. Først må du kontrollere at du har installert redux:

npm installere redux

Bruk Create-React-app eller din favoritt webpack-konfigurasjon for å konfigurere utviklingsserveren. Siden Redux er en uavhengig statlig ledelse, kommer vi ikke til å koble til React ennå. Så fjern innholdet i index.js, og vi vil leke med Redux for resten av denne opplæringen.

butikk

Butikken er et stort JavaScript-objekt som har tonnevis av nøkkelverdige par som representerer nåværende tilstand av applikasjonen. I motsetning til statobjektet i React som er sprinklet over ulike komponenter, har vi bare en butikk. Butikken gir søknadstilstanden, og hver gang staten oppdaterer, blir visningen rerenders. 

derimot, Du kan aldri mutere eller endre butikken. I stedet lager du nye versjoner av butikken. 

(forrige, handling) => newState

På grunn av dette kan du gjøre tidsreise gjennom alle statene fra det tidspunktet appen ble startet på nettleseren din.

Butikken har tre metoder for å kommunisere med resten av arkitekturen. De er:

  • Store.getState () - For å få tilgang til nåværende tilstandstreet i søknaden din. 
  • Store.dispatch (handling) - For å utløse en tilstandsendring basert på en handling. Mer om handlinger nedenfor.
  • Store.subscribe (listener) -Til å høre på eventuelle endringer i staten. Det vil bli kalt hver gang en handling sendes.

La oss lage en butikk. Redux har en Create Metode for å opprette en ny butikk. Du må sende det en reduksjon, selv om vi ikke vet hva det er. Så jeg vil bare opprette en funksjon som kalles reduksjon. Du kan eventuelt angi et annet argument som angir opprinnelig tilstand i butikken. 

src / index.js

importer createStore fra "redux"; // Dette er reduktor const reducer = () => / * Noe går her * / // initialState er valgfritt. // For denne demoen bruker jeg en teller, men vanligvis er tilstanden en objekt const initialState = 0 const store = createStore (reduktor, initialState);

Nå skal vi lytte til eventuelle endringer i butikken, og da console.log () butikkens nåværende tilstand.

store.subscribe (() => console.log ("Staten har endret seg" + store.getState ());) 

Så hvordan oppdaterer vi butikken? Redux har noe kalt handlinger som gjør at dette skjer.

Handling / Handlingsskapere

Handlinger er også enkle JavaScript-objekter som sender informasjon fra din søknad til butikken. Hvis du har en veldig enkel teller med en inkrementsknapp, vil det medføre at en handling utløses som ser slik ut:

type: "INCREMENT", nyttelast: 1

De er den eneste informasjonskilden til butikken. Butikken i butikken endres bare som svar på en handling. Hver handling skal ha en type egenskap som beskriver hva handlingsobjektet har til hensikt å gjøre. Annet enn det, er handlingenes struktur helt opp til deg. Hold imidlertid handlingen liten fordi en handling representerer den minste mengden informasjon som kreves for å transformere programstatusen. 

For eksempel, i eksempelet ovenfor, er typeegenskapen satt til "INCREMENT", og en ekstra nyttelastegenskap er inkludert. Du kan omdøpe nyttelastegenskapen til noe mer meningsfylt eller, i vårt tilfelle, utelate det helt. Du kan sende en handling til butikken som dette.

store.dispatch (type: "INCREMENT", nyttelast: 1); 

Mens du koder Redux, vil du normalt ikke bruke handlinger direkte. I stedet vil du ringe funksjoner som returnerer handlinger, og disse funksjonene er populært kjent som handlingsskapere. Her er handlingsskaperen for inkrementaksjonen som vi diskuterte tidligere.

const incrementCount = (count) => retur type: "INCREMENT", nyttelast: telle

Så, for å oppdatere tilstanden til disken, må du sende den incrementCount handling slik:

store.dispatch (incrementCount (1)); store.dispatch (incrementCount (1)); store.dispatch (incrementCount (1));

Hvis du leder til nettleserkonsollen, ser du at den fungerer, delvis. Vi blir udefinert fordi vi ikke har definert reduksjonsmaskinen ennå.

Så nå har vi dekket handlinger og butikken. Imidlertid trenger vi en mekanisme for å konvertere informasjonen som er gitt av handlingen og forandre tilstanden til butikken. Reduktorer tjener denne hensikten.

reduksjonsgir

En handling beskriver problemet, og reduksjonen er ansvarlig for å løse problemet. I det tidligere eksempelet, incrementCount Metoden returnerte en handling som ga informasjon om hvilken type forandring vi ønsket å gjøre til staten. Reduksjonen bruker denne informasjonen for å faktisk oppdatere staten. Det er et stort poeng uthevet i dokumentene som du alltid bør huske mens du bruker Redux:

Gitt de samme argumentene, bør en Reducer beregne neste tilstand og returnere den. Ingen overraskelser. Ingen bivirkninger. Ingen API-anrop. Ingen mutasjoner. Bare en beregning.

Hva dette betyr er at en reduksjon skal være en ren funksjon. Gitt et sett med innganger, bør det alltid returnere samme utgang. Utover det bør det ikke gjøre noe mer. Dessuten er et reduseringsmiddel ikke stedet for bivirkninger som for eksempel å lage AJAX-anrop eller hente data fra API-en. 

La oss fylle ut reduksjonsmaskinen for våre teller.

// Dette er reduksjon const consterator = (state = initialState, action) => switch (action.type) tilfelle "INCREMENT": returstatus + action.payload standard: returstatus

Reduksjonen aksepterer to argumenter-tilstand og handling - og den returnerer en ny tilstand.

(forrige, handling) => newState

Staten aksepterer en standardverdi, den opprinnelige tilstand, som bare vil bli brukt hvis verdien av staten er udefinert. Ellers vil den faktiske verdien av staten beholdes. Vi bruker bryteretningen til å velge riktig handling. Oppdater nettleseren, og alt fungerer som forventet. 

La oss legge til en sak for minsk, uten hvilken telleren er ufullstendig.

// Dette er reduksjonsreduktoren = (state = initialState, action) => switch (action.type) tilfelle "INCREMENT": returstatus + action.payload case "DECREMENT": returstatus - action.payload standard: returstatus

Her er handlingsskaperen.

const decrementCount = (count) => return type: "DECREMENT", nyttelast: count

Endelig send det til butikken.

store.dispatch (incrementCount (4)); // 4 store.dispatch (decrementCount (2)); // 2

Det er det!

Sammendrag

Denne opplæringen var ment å være et utgangspunkt for å håndtere staten med Redux. Vi har dekket alt som er nødvendig for å forstå de grunnleggende Redux-konseptene, for eksempel butikken, handlinger og reduksjonsverktøy. Mot slutten av opplæringen opprettet vi også en arbeidsredx demo-teller. Selv om det ikke var mye, lærte vi hvordan alle stykkene av puslespillet passer sammen. 

I løpet av de siste par årene har React vokst i popularitet. Faktisk har vi en rekke elementer på markedet som er tilgjengelige for kjøp, gjennomgang, implementering og så videre. Hvis du leter etter flere ressurser rundt React, ikke nøl med å sjekke dem ut.

I neste opplæring vil vi gjøre bruk av de tingene vi har lært her for å lage et React-program ved hjelp av Redux. Hold deg innstilt til da. Del dine tanker i kommentarene.