Acest articol este despre cum să gândești în Redux. Vom încerca să înțelegem cum putem utiliza această minunată bibliotecă pentru a face aplicația noastră mai stabilă, mai robustă și mai ușor de întreținut. Este un limbaj agnostic, cu toate acestea ne vom menține scopul la Redux cu React.

Pentru cei care nu au folosit Redux înainte, voi cita din documente:

Redux este un container de stare previzibil pentru aplicațiile JavaScript.

Este doar o bibliotecă de 2 KB care rezolvă una dintre cele mai mari probleme în menținerea aplicațiilor JavaScript mari: gestionarea stării.

Acest articol nu este despre Redux, deoarece există o mulțime de articole despre acesta deja. Mai degrabă, este vorba despre modul în care ar trebui să vizualizăm o aplicație Redux și să o folosim eficient.

Să presupunem că construim o aplicație de comerț electronic în care are câteva pagini de bază, cum ar fi catalogul, detaliile produsului și succesul plăților.

Mai jos sunt cadrele wireframe ale modului în care ar arăta aplicația:

Cel mai bun mod de a va arhitectura aplicatia
Pagina de catalog
1611945846 937 Cel mai bun mod de a va arhitectura aplicatia
Pagina produsului
1611945846 506 Cel mai bun mod de a va arhitectura aplicatia
Plată reușită

Așadar, arhitectura în Redux înseamnă că trebuie să vizualizăm aplicația ca o singură entitate și fiecare pagină este o subentitate.

Există patru etape pentru crearea unei aplicații Redux:

  1. Vizualizați arborele de stare
  2. Proiectați-vă reductoarele
  3. Implementați acțiuni
  4. Implementați prezentarea

Pasul 1: Vizualizați arborele de stare

Din ramele de mai sus, să proiectăm arborele nostru de stare.

1611945847 987 Cel mai bun mod de a va arhitectura aplicatia
Arborele stării aplicației

Acesta este cel mai important pas. După ce am terminat vizualizarea arborelui nostru de stare, implementarea tehnicilor Redux devine foarte ușoară! Cercurile punctate sunt stări care vor fi partajate de aplicație, cercurile solide sunt stări specifice paginii.

Pasul 2: Proiectați reductoarele

În cazul în care vă întrebați ce este exact un reductor, voi cita direct din documente:

Reductoare specificați modul în care starea aplicației se schimbă ca răspuns la acțiuni trimis la magazin. Amintiți-vă că acțiunile descriu doar Ce s-a întâmplat, dar nu descrieți cum se schimbă starea aplicației.

Fiecare dintre statele importante pot avea propriile lor reductoare. Mai târziu, le putem combina într-un reductor de rădăcină care va defini în cele din urmă magazinul (singura sursă de adevăr a aplicației). Aici intervine puterea reală: aveți control total asupra stărilor voastre și asupra comportamentului lor. Nimic nu este vizionat de magazin. Observatorul tăcut veghează.

Cel mai bun mod de a va arhitectura aplicatia
Magazinul care veghează

Să vedem un exemplu de cum să proiectăm un reductor cu ajutorul arborelui stării aplicației pe care l-am proiectat mai sus.

// Root Reducer
const rootReducer = combineReducer({  
    header: headerReducer,  
    login: loginReducer,  
    footer: footerReducer,  
    common: commonReducer,  
    product: productReducer,  
    catalog: catalogReducer,  
    payment: paymentReducer
});
Reductor de rădăcină

Reductorul de rădăcină spune totul. Conține tot ce trebuie să știe magazinul despre aplicație.

Acum să vedem cum arată o sub entitate headerReducer.

Vă amintiți cum ne-am proiectat starea antetului?

1611945847 426 Cel mai bun mod de a va arhitectura aplicatia
Arborele stării antetului
// Header Reducer

const headerReducer = combineReducer({
    menu: menuReducer,  
    search: searchReducer,  
    location: locationReducer
});

Reductorul nostru este o replică a ceea ce am proiectat mai devreme în arborele nostru de stat. Aceasta este puterea vizualizării.

Observați cum un reductor conține mai multe reductoare. Nu este nevoie să creăm un reductor imens. Poate fi ușor divizat în reductoare mai mici, deoarece fiecare își păstrează identitățile individuale și are propriile operațiuni specifice. Acest lucru ne ajută să creăm separarea logicii, ceea ce este foarte important pentru menținerea aplicațiilor mari.

Acum să înțelegem cum ar trebui configurat un fișier reductor tipic, de exemplu searchReducer.

// Search Reducer

const initialState = {  payload: [],  isLoading: false,  error: {}};

export function searchReducer( state=initialState, action ) { 	 
    switch(action.type) {    
        case FETCH_SEARCH_DATA:      
            return {        
                	...state,        
                    isLoading: true    
            };        
        case FETCH_SEARCH_SUCCESS:      
            return {        
	                ...state,        
                    payload: action.payload,        
                    isLoading: false      
                   };        
        case FETCH_SEARCH_FAILURE:      
            return {        
	                ...state,        
                    error: action.error,        
                    isLoading: false            
            };
                
        case RESET_SEARCH_DATA:      
            return { ...state, ...initialState }        
		default:      return state;
    }
}

Acest model reductor definește modificările posibile în starea sa de căutare atunci când se apelează API-ul de căutare.

FETCH_SEARCH_DATA, FETCH_SEARCH_SUCCESS, FETCH_SEARCH_FAILURE, RESET_SEARCH_DATA

Toate cele de mai sus sunt constante posibile care definesc ceea ce este posibil acțiuni poate fi efectuată.

Notă: Este important să menținem o acțiune RESET_SEARCH_DATA, în cazul în care trebuie să resetăm datele în timpul demontării unei componente.

Pasul 3: Implementați acțiuni

Fiecare acțiune care are apeluri API trece de obicei prin trei etape într-o aplicație.

  1. Starea de încărcare -> FETCH_SEARCH_DATA
  2. Succes -> FETCH_SEARCH_SUCCESS
  3. Eșec -> FETCH_SEARCH_FAILURE

Menținerea acestor tipuri de acțiuni ne ajută să verificăm fluxul de date atunci când este apelat un API în aplicația noastră.

Să ne scufundăm în cod pentru a înțelege cum va arăta o acțiune tipică.

export function fetchSearchData(args) {  
	return async (dispatch) => {    
        // Initiate loading state    
        dispatch({      
            type: FETCH_SEARCH_DATA    
        });
        try {      
            // Call the API      
            const result = await fetchSearchData(
                args.pageCount, 
                args.itemsPerPage
            );           
            // Update payload in reducer on success     
            dispatch({        
                type: FETCH_SEARCH_SUCCESS,        
                payload: result,        
                currentPage: args.pageCount      
            });    
        } catch (err) {     
            // Update error in reducer on failure           
            dispatch({        
                type: FETCH_SEARCH_FAILURE,        
                error: err      
            });    
        }  
    };
}

Observați modul în care fluxul de date este urmărit de magazin prin acțiuni. Astfel, fiecare schimbare a aplicației este responsabilă.

Astfel, sunt scrise acțiuni similare pentru fiecare modificare a reductorilor din diferite stări.

Unul dintre cele mai mari beneficii ale Redux este abstractizarea fiecărei acțiuni.

1611945847 406 Cel mai bun mod de a va arhitectura aplicatia
Flux de date într-o aplicație Redux

Pasul 4: Implementați prezentarea

import React, { Component } from 'react';
import { connect } from 'react-redux';;

import fetchSearchData from './action/fetchSearchData';
import SearchData from './SearchData';

const Search = (props) => (  
    <SearchData     
    	search={props.search}    
		fetchSearchData={props.fetchSearchData}   
	/>
);

const mapStateToProps = (state) => ({  
    search: state.header.search.payload
});

const mapDispatchToProps = {  fetchSearchData};

export default connect(mapStateToProps, mapDispatchToProps)(Search)

După cum puteți vedea, componenta de prezentare este foarte simplă și ușor de înțeles.

Concluzie

Aș dori să menționez câteva dintre cele mai mari beneficii pe care le-am găsit folosind Redux:

  1. Cu siguranță reduce mirosul de cod.
  2. Abstracția codului este mai ușor de realizat.
  3. Redux ne introduce, de asemenea, în alte principii precum imuabilitatea, programarea funcțională și multe altele.
  4. Vă permite să vizualizați fiecare acțiune și să le urmăriți cu „călătoria în timp”.

Sper că acest articol vă va ajuta să obțineți o imagine mai clară a motivului pentru care Redux este cu adevărat minunat și cum putem folosi puterea vizualizării pentru a crea aplicații care pot fi întreținute.

Urmează-mă pe mine stare de nervozitate pentru a primi mai multe actualizări cu privire la articolele noi și pentru a fi la curent cu cele mai recente dezvoltări frontend. De asemenea, trimiteți acest articol pe Twitter pentru a-i ajuta pe ceilalți să știe despre el. Împărtășirea înseamnă grijă ^ _ ^.

Câteva resurse utile

  1. https://redux.js.org/
  2. https://github.com/reduxjs/redux/blob/master/examples
  3. https://medium.com/@rajaraodv/a-guide-for-building-a-react-redux-crud-app-7fe0b8943d0f#.c4yhhvk0d

Articolele mele anterioare

  1. https://medium.freecodecamp.org/how-to-use-redux-persist-when-migrating-your-states-a5dee16b5ead
  2. https://codeburst.io/redux-observable-to-the-rescue-b27f07406cf2
  3. https://codeburst.io/building-webapp-for-the-future-68d69054cbbd
  4. https://codeburst.io/cors-story-of-requesting-twice-85219da7172d