Kako implementirati Redux u 24 retka JavaScript-a

90% konvencije, 10% knjižnice.

Redux je jedna od najvažnijih JavaScript knjižnica ikad stvorenih. Inspiriran prethodnom umjetnošću poput Fluxa i Elma, Redux je na kartu stavio JavaScript funkcionalno programiranje uvođenjem skalabilne arhitekture od tri jednostavne točke.

Ako ste novi u Reduxu, prvo razmislite o čitanju službenih dokumenata.

Redux je uglavnom konvencija

Razmotrite ovu jednostavnu brojačku aplikaciju koja koristi Redux arhitekturu. Ako želite skočiti, provjerite Github repo za njega.

redux-counter-app-demo

Država živi u jednom stablu

Stanje aplikacije izgleda ovako.

const initialState = { count: 0 }; 

Akcije proglašavaju promjene stanja

Redux konvencijom ne izravno modificiram (mutiram) stanje.

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

Umjesto toga stvaram sve radnje koje korisnik može iskoristiti u aplikaciji.

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

Reduktor tumači radnje i ažurira stanje

Posljednji arhitektonski komad traži reduktor, čistu funkciju koja vraća novu kopiju vašeg stanja na temelju prethodnog stanja i radnje.

  • Ako incrementse otpusti, povećajte state.count.
  • Ako decrementse otpusti, umanji 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; } }; 

Za sada nema Reduxa

Jeste li primijetili da još nismo dodirnuli knjižnicu Redux? Upravo smo stvorili neke objekte i funkciju. To je ono što mislim pod "uglavnom konvencijom", 90% Reduxa ne zahtijeva Redux!

Provedimo Redux

Da bismo ovu arhitekturu koristili, moramo je priključiti u trgovinu. Provest ćemo samo jednu funkciju– createStore.

Koristi se ovako.

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 evo našeg početnog uzorka. Trebat će nam popis slušatelja i početno stanje koje daje reduktor.

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

Kad god se netko pretplati na našu trgovinu, dodaje se u listenersniz. Važno je jer svaki put kad netko pošalje akciju, svi listenersmoraju biti obaviješteni u petlji.

Pozivanje yourReducers undefinedpraznim objektom vraća prethodno initialStateinstalirano. To nam daje odgovarajuću vrijednost koju možemo vratiti kad nazovemo store.getState(). Kad smo već kod toga, stvorimo tu metodu.

store.getState ()

Ovo je funkcija koja vraća najnovije stanje iz trgovine. To će nam trebati za ažuriranje našeg korisničkog sučelja svaki put kad korisnik klikne gumb.

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

store.dispatch (akcija)

Ovo je funkcija koja uzima actionparametar an . Hrani to actioni ono currentStateda yourReducerbi dobilo novu državu. Zatim dispatchobavještava sve pretplaćene na 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 (slušatelj)

Ovo je funkcija koja vam omogućuje da budete obaviješteni kada trgovina primi radnju. Ovdje je dobro koristiti store.getState()vaše najnovije stanje i ažurirati svoje korisničko sučelje.

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; } }; }; 

subscribevraća funkciju pozvanu unsubscribekoju možete nazvati kada više ne želite slušati ažuriranja trgovine.

Sada svi zajedno

Priključimo ovo na naše gumbe i pogledajmo konačni izvorni kod.

// 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 još jednom evo našeg konačnog korisničkog sučelja.

redux-counter-app-demo

Ako vas zanima HTML / CSS koji sam koristio, evo ponovno GitHub repo-a!

Želite besplatni trening?

Ako želite zakazati besplatan poziv za raspravu o Front-end razvojnim pitanjima u vezi s kodom, intervjuima, karijerom ili nečim drugim, slijedite me na Twitteru i DM-u.

Nakon toga, ako uživate u našem prvom sastanku, možemo razgovarati o kontinuiranom treningu koji će vam pomoći da postignete svoje Front-end razvojne ciljeve!

Nosite svoje doprinose

Ako kodirate svaki dan, pogotovo ako se obvezujete na GitHub, ne bi li bilo lijepo nositi tu kartu doprinosa da je svi vide?

Gitmerch.com vam omogućuje ispis majice vaše karte s doprinosima za GitHub! Koristite kod Yazeed na blagajni za popust.

git-merch-screenshot-1-1

git-merch-screenshot-2-1

Hvala na čitanju

Za više ovakvih sadržaja pogledajte //yazeedb.com!

Do sljedećeg puta!