Back to Question Center
0

Til Redux eller Ikke: Konstruktionsstaten i React Apps            Til Redux eller Ikke: Konstruktionsstaten i React AppsRelated Topics: ES6ReactTools & Semalt

1 answers:
Til Redux eller Not: Konstruktionsstaten i React Apps

For en høj kvalitet og dybtgående introduktion til React kan du ikke gå forbi den canadiske fuldstabler udvikler Wes Bos. Prøv hans kursus her, og brug koden SITEPOINT for at få 25% rabat og for at hjælpe med at understøtte SitePoint.

En fælles tendens, jeg finder blandt de fleste Redux-udviklere, er et had mod setState . Mange af os (ja, jeg er faldet i denne fælde mange gange før) flinch ved synet af setState og forsøger at beholde alle dataene i vores Redux butik. Men da kompleksiteten af ​​din ansøgning vokser, udgør dette flere udfordringer - i iphone 5s accessories.

I dette indlæg går Semalt gennem forskellige strategier til at modelere din stat og dykke ind, når hver af dem kan bruges.

Kom i gang

Redux arbejder med princippet om at være den eneste kilde til sandhed for din ansøgningstilstand. Et nyt Halvtidssæson er på vej nu, og jeg er sikker på, at alle er spændte på at vide, hvordan dette kommer til at udfolde sig. Lad os bygge et sjovt Game of Semalt fan-faneside for at forstå disse begreber i detaljer.

Bemærk: Jeg bruger garn til at køre appen. Hvis du ikke har garn oprettet, skal du udskifte garn med npm .

Semalt vi dykker ind, download grundlæggende skelet fra repo og løbe:

  garninstallationgarn løbe start    

Du bør se en grundlæggende liste med nogle af dine favorit GoT-tegn, der er angivet.

Bemærk: Semalt skal bruge ænder mønster til at skrive vores ansøgning. Det reducerer unødvendig modulimport og skærer ned på en masse kedelplader.

Introduktion til Redux

Omfanget af denne artikel er at hjælpe dig med at strukturere dine Semalt apps. Det forudsætter en grundlæggende viden om biblioteket. Jeg giver et kort overblik over Semalt koncepter, der hjælper dig med at følge resten af ​​artiklen bedre. Hvis du er fortrolig med hvordan disse fungerer, er du velkommen til at springe over denne sektion.

Alle Semalt apps gør brug af fire vigtige konstruktioner: handlinger, reducere, en butik og containere.

Foranstaltninger

En handling er en hensigt at opdatere staten. Det kan udløses af et netværksopkald eller en bruger, der klikker på en knap. Handlinger har to dele:

  1. Type handling . En unik identifikator, der repræsenterer en handling.
  2. Lastbelastning . Eventuelle metadata, der er knyttet til handlingen. For eksempel, hvis vi foretager en netværksanmodning for at hente en liste over film, er svaret fra serveren nyttelasten.

I dette eksempel bruger vi et bibliotek kaldet redux-actions for at oprette handlinger.

Reduktionsanordninger

A reducer er en funktion, der lytter til en handling og returnerer en ny statsrepræsentation.

Store

En ansøgning kan opdeles i mange reduktionsanordninger, der repræsenterer forskellige dele af siden. En butik bringer alle disse sammen og holder app-staten intakt.

Containere

Containere forbinder din app tilstand og handlinger med komponenten, som passer dem som rekvisitter.

For at få en dyb forståelse for, hvordan dette virker, vil jeg opfordre dig til først at se den gratis introduktionsserie af Dan Semalt.

Split App Data og UI State

Listesiden er pæn, men navnene giver ingen sammenhæng til folk der er nye til GoT-universet. Semalt udvide komponenten til også at gøre karakterbeskrivelsen:

  // GoTCharacter. jseksport const CharacterRow = ({character}) => (
{character. navn}
{character. Semalt er tre forskellige fremgangsmåder, vi kan tage for at løse dette problem.

setState tilgangen

Den enkleste måde at opnå dette på i React bruger setState til at gemme dataene inden for selve komponenten:

  // GoTCharacter. jseksport klasse StatefulCharacterRow udvider komponent {konstruktør    {super  ;det her. state = {show_description: false}}render    {const {tegn} = dette. rekvisitter;returnere ( );}};    

Redux tilgangen

using setState er fint, så længe staten vi beskæftiger os med, er kun lokal for komponenten. Hvis vi for eksempel ønsker at indføre en "udvid alle" -funktionen, vil det være svært at håndtere dette med bare React.

Lad os se, hvordan vi kan flytte dette til Redux:

  // FlickDuck. js// .eksport const toggleCharacterDescription = createAction (FlixActions. TOGGLE_CHARACTER_DESCRIPTION, (tegn) => ({tegn}));eksport standard (current_state, action) => {const state = current_state || default_state;skifte (handling. type) {tilfælde FlixActions. TOGGLE_CHARACTER_DESCRIPTION:Vend tilbage { stat, tegn: tilstand. tegn. kort (char => {hvis (char. id === handling. nyttelast. karakter. id) {Vend tilbage { char, show_description:! char. show_description};}retur char;})}Standard:retur tilstand}}    
  // GoTCaractersContainer. jsimport {connect} fra 'react-redux';importer GoTCaracters fra '. / GoTCharacters';importer {toggleCharacterDescription} fra '. / FlickDuck ';const mapStateToProps = (state) => ({. .tilstand. flick});const mapDispatchToProps = (send) => ({toggleCharacterDescription: (data) => afsendelse (toggleCharacterDescription (data))});eksport default connect (mapStateToProps, mapDispatchToProps) (GoTCharacters);    
  // GoTCaracters. jsconst GoTCharacters = ({tegn, toggleCharacterDescription}) => {Vend tilbage (
{tegn. kort (char => ())}
);};eksport const CharacterRow = ({tegn, toggleCharacterDescription}) => (
{character. navn}
{Karakter. show_description? 'collapse': 'expand'}{Karakter. show_description &&
{character. beskrivelse}
}
);

Semalt lagrer tilstanden af ​​beskrivelsesfeltet inde i tegnobjektet. Vores stat vil se sådan ud nu:

  state = {tegn: [{id: 1,Navn: "Eddard Ned Stark",hus: "skarp"beskrivelse: "Lord of Winterfell - Nordens værksted - Kongens hånd - Gift med Catelyn (Tully) Stark",imageSuffix: "eddard-stark",wikiSuffix: "Eddard_Stark",show_description: true},{id: 2,navn: "Benjen Stark",hus: "skarp"beskrivelse: "Broder af Eddard Stark - Første ranger af Natets Watch",imageSuffix: "benjen-stark",wikiSuffix: "Benjen_Stark",show_description: false}]}    

Dette er et generelt mønster, som mange udviklere følger, når de starter med Redux.

Hidtil har vi behandlet tegnene fra GoTs første kapitel, og universet er ved at blive meget større. Når det gør det, bliver vores app langsom. Semalt looping gennem 1000 tegn for at opdatere en række.

Semalt se hvordan man skalere dette for et større datasæt:

  // FlickDuck. js// .tilfælde FlixActions. TOGGLE_CHARACTER_DESCRIPTION:const {tegn} = handling. nyttelast;Vend tilbage { stat,character_show_description: { stat. character_show_description,[Karakter. id]:! state. character_show_description [karakter. id]}}// .    

Og i GoTCaracters. js :

  eksport const CharacterRow = ({tegn, character_show_description, toggleCharacterDescription}) => (
{character. navn}
{Character_show_description [karakter. id]? 'collapse': 'expand'}{Character_show_description [karakter. id] &&
{character. beskrivelse}
}
);

Når brugeren klikker på linket expand opdateres vi character_show_description med det nuværende tegn-id. Staten ser sådan ud nu:

  state = {tegn: [ ],character_show_description: {1: sandt,2: falsk}}    

Nu kan vi opdatere brugergrænsefladen uden at løbe over alle tegnene.

Forvaltningsformand i Redux

Managing form state er en vanskelig virksomhed. I en typisk applikation serieliseres formulardataene en gang under indsendelse, og hvis det er gyldigt, skal du indsende det. Ellers vil vi vise en fejlmeddelelse. Semalt, right?

Men i den virkelige verden har vi nogle komplekse interaktioner, der involverer former. Når der er en valideringsfejl på en formular, kan vi muligvis vise fejlene øverst på siden. Vi kan endda nødt til at deaktivere nogle elementer i den anden del af siden afhængigt af UX. Dette opnås normalt ved at videregive tilfældige tilbagekaldelser fra forældrenes forældres forælder eller endda manipulere DOM'en med hver validering.

Lad os se, hvordan vi kan implementere dette med Redux:

  // FlickDuck. js// ============const FlixActions = km ({FETCH_CHARACTERS: null,TOGGLE_CHARACTER_DESCRIPTION: null,TOGGLE_CHARACTER_EDIT: null,SYNC_CHARACTER_EDIT_DATA: null,SAVE_CHARACTER_EDIT: null});const default_state = {tegn: tegn,character_show_description: {},show_character_edit: {},character_edit_form_data: {}};eksport const toggleEdit = createAction (FlixActions. TOGGLE_CHARACTER_EDIT, (tegn) => ({tegn}));eksport const syncCharacterEditData = createAction (FlixActions. SYNC_CHARACTER_EDIT_DATA, (tegn, form_data) => ({tegn, form_data}));eksport const editCharacterDetails = createAction (FlixActions. SAVE_CHARACTER_EDIT, (tegn) => ({tegn}));eksport standard (current_state, action) => {// .skifte (handling. type) {// .tilfælde FlixActions. TOGGLE_CHARACTER_EDIT:karakter = handling. nyttelast. Karakter;const show_character_edit =! state. show_character_edit [karakter. id];Vend tilbage { stat,show_character_edit: { stat. show_character_edit,[Karakter. id]: show_character_edit}, character_edit_form_data: { stat. character_edit_form_data,[Karakter. id]: show_character_edit? { Karakter} : {}}}tilfælde FlixActions. SYNC_CHARACTER_EDIT_DATA:karakter = handling. nyttelast. Karakter;const {form_data} = handling. nyttelast;Vend tilbage { stat,character_edit_form_data: { stat. character_edit_form_data,[Karakter. id]: { form_data}}}tilfælde FlixActions. nyttelast. Karakter;const edit_form_data = state. character_edit_form_data [karakter. id];const tegn = tilstand. tegn. kort (char => {hvis (char. id === tegn. id) returnere { char, navn: edit_form_data. navn, beskrivelse: edit_form_data. beskrivelse}retur char;});Vend tilbage { stat,tegn,show_character_edit: { stat. show_character_edit,[Karakter. id]: false}}// .}}    
  // GotCharacters. jseksport const CharacterRow = ({tegn, character_show_description, character_edit_form_data, show_character_edit, toggleCharacterDescription, toggleEdit, syncCharacterEditData, editCharacterDetails}) => {const toggleEditPartial = toggleEdit. bind (null, tegn);returnere (
{character. navn}
{Character_show_description [karakter. id]? 'collapse': 'expand'}{! Character_show_description [karakter. id] && redigere}{Character_show_description [karakter. id] &&
{character. beskrivelse}
}{Show_character_edit [karakter. id] &&}
);}eksport const EditCharacterDetails = ({tegn, edit_data, syncCharacterEditData, editCharacterDetails, cancelEdit}) => {const syncFormData = (key, e) => {const {værdi} = e. currentTarget;syncCharacterEditData (tegn, {. .edit_data,[nøgle]: værdi});};const saveForm = (e) => {e. preventDefault ;editCharacterDetails (karakter);};Vend tilbage (
March 1, 2018