90% convenție, 10% bibliotecă.

Redux este printre cele mai importante biblioteci JavaScript create vreodată. Inspirat de tehnica anterioară, cum ar fi Flux și Ulm, Redux a pus programarea funcțională JavaScript pe hartă prin introducerea unei arhitecturi scalabile de trei puncte simple.

Dacă sunteți nou în Redux, vă recomandăm să citiți documentele oficiale primul.

Redux este cea mai mare parte a convenției

Luați în considerare această aplicație simplă de contor care utilizează arhitectura Redux. Dacă doriți să mergeți mai departe, verificați repo Github pentru aceasta.

redux-counter-app-demo

Statul trăiește într-un singur copac

Starea aplicației arată astfel.

const initialState = { count: 0 };

Acțiunile declară modificări de stare

Prin convenția Redux, eu nu modificați direct (mutați) starea.

// DON'T do this in a Redux app
state.count = 1;

În schimb, creez toate acțiunile pe care utilizatorul le poate folosi în aplicație.

const actions = {
  increment: { type: 'INCREMENT' },
  decrement: { type: 'DECREMENT' }
};

Reducerul interpretează acțiunea și actualizează starea

Ultima piesă arhitecturală necesită un reductor, o funcție pură care returnează o nouă copie a stării dvs. pe baza stării și acțiunii anterioare.

  • Dacă increment este concediat, increment state.count.
  • Dacă decrement este concediat, decret state.count.
const countReducer = (state = initialState, action) => {
  switch (action.type) {
    case actions.increment.type:
      return {
        count: state.count + 1
      };

    case actions.decrement.type:
      return {
        count: state.count - 1
      };

    default:
      return state;
  }
};

Fără Redux până acum

Ai observat că nu am atins încă biblioteca Redux? Tocmai am creat câteva obiecte și o funcție. Aceasta este ceea ce vreau să spun prin „cea mai mare parte convenție”, 90% din Redux nu necesită Redux!

Să implementăm Redux

Pentru a folosi această arhitectură, trebuie să o conectăm la un magazin. Vom implementa o singură funcție –createStore.

Se folosește așa.

import { createStore } from 'redux'

const store = createStore(countReducer);

store.subscribe(() => {
  console.log(store.getState());
});

store.dispatch(actions.increment);
// logs { count: 1 }

store.dispatch(actions.increment);
// logs { count: 2 }

store.dispatch(actions.decrement);
// logs { count: 1 }

Și iată căldura noastră inițială. Vom avea nevoie de o listă de ascultători și de starea inițială furnizată de reductor.

const createStore = (yourReducer) => {
    let listeners = [];
    let currentState = yourReducer(undefined, {});
}

Ori de câte ori cineva se abonează la magazinul nostru, este adăugat la listeners matrice. Este important pentru că de fiecare dată când cineva trimite o acțiune, toate listeners trebuie notificat în buclă.

Apelare yourReducer cu undefined iar un obiect gol returnează fișierul initialState am instalat mai sus. Acest lucru ne oferă o valoare adecvată de returnat atunci când sunăm store.getState(). Apropo de asta, să creăm această metodă.

store.getState ()

Aceasta este o funcție care returnează cea mai recentă stare din magazin. Vom avea nevoie de acest lucru pentru a ne actualiza interfața de utilizare de fiecare dată când utilizatorul dă clic pe un buton.

const createStore = (yourReducer) => {
    let listeners = [];
    let currentState = yourReducer(undefined, {});
    
    return {
        getState: () => currentState
    };
}

store.dispatch (acțiune)

Aceasta este o funcție care necesită un action ca parametru. Hrănește asta action si currentState la yourReducer a primi o nou stat. Apoi dispatch notifică pe toți cei abonați la store.

const createStore = (yourReducer) => {
  let listeners = [];
  let currentState = yourReducer(undefined, {});

  return {
    getState: () => currentState,
    dispatch: (action) => {
      currentState = yourReducer(currentState, action);

      listeners.forEach((listener) => {
        listener();
      });
    }
  };
};

store.subscribe (ascultător)

Aceasta este o funcție care vă permite să fiți notificat atunci când magazinul primește o acțiune Este bine de utilizat store.getState() aici pentru a obține cea mai recentă stare și a vă actualiza interfața de utilizare.

const createStore = (yourReducer) => {
  let listeners = [];
  let currentState = yourReducer(undefined, {});

  return {
    getState: () => currentState,
    dispatch: (action) => {
      currentState = yourReducer(currentState, action);

      listeners.forEach((listener) => {
        listener();
      });
    },
    subscribe: (newListener) => {
      listeners.push(newListener);

      const unsubscribe = () => {
        listeners = listeners.filter((l) => l !== newListener);
      };

      return unsubscribe;
    }
  };
};

subscribe returnează o funcție numită unsubscribe pe care îl puteți apela atunci când nu mai sunteți interesat să ascultați actualizările magazinului.

Toti impreuna acum

Să conectăm acest lucru la butoanele noastre și să vedem codul sursă final.

// simplified createStore function
const createStore = (yourReducer) => {
  let listeners = [];
  let currentState = yourReducer(undefined, {});

  return {
    getState: () => currentState,
    dispatch: (action) => {
      currentState = yourReducer(currentState, action);

      listeners.forEach((listener) => {
        listener();
      });
    },
    subscribe: (newListener) => {
      listeners.push(newListener);

      const unsubscribe = () => {
        listeners = listeners.filter((l) => l !== newListener);
      };

      return unsubscribe;
    }
  };
};

// Redux architecture pieces
const initialState = { count: 0 };

const actions = {
  increment: { type: 'INCREMENT' },
  decrement: { type: 'DECREMENT' }
};

const countReducer = (state = initialState, action) => {
  switch (action.type) {
    case actions.increment.type:
      return {
        count: state.count + 1
      };

    case actions.decrement.type:
      return {
        count: state.count - 1
      };

    default:
      return state;
  }
};

const store = createStore(countReducer);

// DOM elements
const incrementButton = document.querySelector('.increment');
const decrementButton = document.querySelector('.decrement');

// Wire click events to actions
incrementButton.addEventListener('click', () => {
  store.dispatch(actions.increment);
});

decrementButton.addEventListener('click', () => {
  store.dispatch(actions.decrement);
});

// Initialize UI display
const counterDisplay = document.querySelector('h1');
counterDisplay.innerHTML = parseInt(initialState.count);

// Update UI when an action fires
store.subscribe(() => {
  const state = store.getState();

  counterDisplay.innerHTML = parseInt(state.count);
});

Și încă o dată aici este interfața noastră finală de utilizare.

redux-counter-app-demo

Dacă sunteți interesat de HTML / CSS pe care l-am folosit, iată repo GitHub din nou!

Vrei antrenament gratuit?

Dacă doriți să programați un apel gratuit pentru a discuta întrebări de dezvoltare Front-End cu privire la cod, interviuri, carieră sau orice altceva urmărește-mă pe Twitter și dă-mi drumul.

După aceea, dacă vă bucurați de prima noastră întâlnire, putem discuta despre un coaching continuu pentru a vă ajuta să vă atingeți obiectivele de dezvoltare Front-End!

Purtă-ți contribuțiile

Dacă codificați în fiecare zi, mai ales dacă vă angajați în GitHub, nu ar fi bine să purtați acea hartă a contribuției pentru ca toți să o vadă?

Gitmerch.com vă permite să imprimați un tricou al hărții dvs. de contribuții GitHub! Folosiți codul, Yazeed, la plată pentru reducere.

git-merch-screenshot-1-1

git-merch-screenshot-2-1

Mulțumesc pentru lectură

Pentru mai mult conținut de genul acesta, verificați https://yazeedb.com!

Pana data viitoare!