Πώς να εφαρμόσετε το Redux σε 24 γραμμές JavaScript

90% σύμβαση, 10% βιβλιοθήκη.

Το Redux είναι από τις πιο σημαντικές βιβλιοθήκες JavaScript που δημιουργήθηκαν ποτέ. Εμπνευσμένο από την προηγούμενη τέχνη όπως το Flux και το Elm, ο Redux έβαλε λειτουργικό προγραμματισμό JavaScript στο χάρτη, εισάγοντας μια κλιμακούμενη αρχιτεκτονική τριών απλών σημείων.

Εάν είστε νέοι στο Redux, σκεφτείτε πρώτα να διαβάσετε τα επίσημα έγγραφα.

Το Redux είναι κυρίως Σύμβαση

Εξετάστε αυτήν την απλή εφαρμογή μετρητή που χρησιμοποιεί την αρχιτεκτονική Redux. Αν θέλετε να προχωρήσετε, ρίξτε μια ματιά στο repo Github για αυτό.

redux-counter-app-demo

Το κράτος ζει σε ένα μόνο δέντρο

Η κατάσταση της εφαρμογής μοιάζει με αυτήν.

const initialState = { count: 0 }; 

Οι ενέργειες δηλώνουν αλλαγές κατάστασης

Με τη σύμβαση Redux, δεν τροποποιώ άμεσα (μεταλλάξω) την κατάσταση.

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

Αντίθετα, δημιουργώ όλες τις ενέργειες που μπορεί να χρησιμοποιήσει ο χρήστης στην εφαρμογή.

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

Ο μειωτής ερμηνεύει τη δράση και την κατάσταση ενημερώσεων

Το τελευταίο αρχιτεκτονικό κομμάτι απαιτεί έναν μειωτή, μια καθαρή λειτουργία που επιστρέφει ένα νέο αντίγραφο της κατάστασής σας με βάση την προηγούμενη κατάσταση και δράση.

  • Εάν incrementπυροδοτηθεί, αυξήστε state.count.
  • Εάν decrementπυροδοτηθεί, μειώστε 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; } }; 

Δεν υπάρχει Redux μέχρι τώρα

Παρατηρήσατε ότι δεν έχουμε αγγίξει τη βιβλιοθήκη Redux ακόμα; Μόλις δημιουργήσαμε κάποια αντικείμενα και μια συνάρτηση. Αυτό εννοώ με τον όρο "κυρίως σύμβαση", το 90% του Redux δεν απαιτεί Redux!

Ας εφαρμόσουμε το Redux

Για να χρησιμοποιήσουμε αυτήν την αρχιτεκτονική, πρέπει να την συνδέσουμε σε ένα κατάστημα. Θα εφαρμόσουμε μόνο μία λειτουργία– createStore.

Χρησιμοποιείται έτσι.

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 } 

Και εδώ είναι το αρχικό μας boilerplate. Θα χρειαστούμε μια λίστα ακροατών και την αρχική κατάσταση που παρέχεται από τον μειωτή.

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

Κάθε φορά που κάποιος εγγράφεται στο κατάστημά μας, προστίθεται στον listenersπίνακα. Αυτό είναι σημαντικό γιατί κάθε φορά που κάποιος αποστέλλει μια ενέργεια, όλα listenersπρέπει να ειδοποιούνται σε έναν βρόχο.

Η κλήση yourReducerμε undefinedκαι ένα κενό αντικείμενο επιστρέφει το παραπάνω initialStateπου εγκαταστήσαμε. Αυτό μας δίνει μια σωστή τιμή για να επιστρέψουμε όταν καλούμε store.getState(). Μιλώντας για αυτό, ας δημιουργήσουμε αυτήν τη μέθοδο.

store.getState ()

Αυτή είναι μια συνάρτηση που επιστρέφει την τελευταία κατάσταση από το κατάστημα. Θα το χρειαζόμαστε για να ενημερώνουμε το περιβάλλον χρήστη μας κάθε φορά που ο χρήστης κάνει κλικ σε ένα κουμπί.

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

store.dispatch (δράση)

Αυτή είναι μια συνάρτηση που λαμβάνει actionως παράμετρο. Τροφοδοτεί αυτό actionκαι currentStateγια yourReducerνα πάρει μια νέα κατάσταση. Στη συνέχεια dispatchειδοποιεί όλους τους εγγεγραμμένους στο 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 (ακροατής)

Αυτή είναι μια λειτουργία που σας επιτρέπει να ειδοποιείτε όταν το κατάστημα λαμβάνει μια ενέργεια. Είναι καλό να το χρησιμοποιήσετε store.getState()εδώ για να λάβετε την τελευταία σας κατάσταση και να ενημερώσετε το περιβάλλον χρήστη σας.

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επιστρέφει μια λειτουργία που ονομάζεται unsubscribeπου μπορείτε να καλέσετε όταν δεν ενδιαφέρεστε πλέον να ακούτε τις ενημερώσεις του καταστήματος.

Ολοι μαζί τώρα

Ας συνδέσουμε αυτό με τα κουμπιά μας και να δούμε τον τελικό πηγαίο κώδικα.

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

Και για άλλη μια φορά εδώ είναι το τελικό περιβάλλον χρήστη μας.

redux-counter-app-demo

Εάν ενδιαφέρεστε για το HTML / CSS που χρησιμοποίησα, εδώ είναι το GitHub repo ξανά!

Θέλετε δωρεάν καθοδήγηση;

Αν θέλετε να προγραμματίσετε μια δωρεάν κλήση για να συζητήσετε ερωτήσεις ανάπτυξης Front-End σχετικά με κώδικα, συνεντεύξεις, καριέρα ή οτιδήποτε άλλο ακολουθήστε με στο Twitter και DM μου.

Μετά από αυτό, αν απολαμβάνετε την πρώτη μας συνάντηση, μπορούμε να συζητήσουμε μια συνεχή καθοδήγηση για να σας βοηθήσουμε να επιτύχετε τους αναπτυξιακούς σας στόχους!

Φορέστε τις συνεισφορές σας

Εάν κωδικοποιείτε καθημερινά, ειδικά αν δεσμεύεστε στο GitHub, δεν θα ήταν ωραίο να φοράτε αυτόν τον χάρτη συνεισφοράς για να το δουν όλοι;

Το Gitmerch.com σας επιτρέπει να εκτυπώσετε ένα μπλουζάκι του χάρτη συνεισφοράς του GitHub! Χρησιμοποιήστε τον κωδικό, Yazeed , στο ταμείο για έκπτωση.

git-merch-screenshot-1-1

git-merch-screenshot-2-1

Ευχαριστώ για την ανάγνωση

Για περισσότερο περιεχόμενο όπως αυτό, δείτε το //yazeedb.com!

Μέχρι την επόμενη φορά!