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.
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
increment
se otpusti, povećajtestate.count
. - Ako
decrement
se otpusti, umanjistate.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 listeners
niz. Važno je jer svaki put kad netko pošalje akciju, svi listeners
moraju biti obaviješteni u petlji.
Pozivanje yourReducer
s undefined
praznim objektom vraća prethodno initialState
instalirano. 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 action
parametar an . Hrani to action
i ono currentState
da yourReducer
bi dobilo novu državu. Zatim dispatch
obavješ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; } }; };
subscribe
vraća funkciju pozvanu unsubscribe
koju 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.
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.
Hvala na čitanju
Za više ovakvih sadržaja pogledajte //yazeedb.com!
Do sljedećeg puta!