By Yazeed Bzadough

In order to ensure the readability of the article, free translation is used instead of literal translation.


90% protocol, 10% library. Redux is one of the most important JavaScript libraries ever created. Inspired by previous arts such as Flux and Elm, Redux makes JavaScript functional programming possible by introducing a scalable architecture with three simple points. If you’re new to Redux, consider reading the official documentation first.

1. Redux is mostly protocol

Consider the following simple counter application using the Redux architecture. Check out the Github Repo if you want to skip ahead.

1.1 State is stored in a tree

The state of the application looks like this:

const initialState = { count: 0 };
Copy the code

1.2 Action Declares the status change

According to the Redux protocol, we do not modify the state directly.

// Do not do the following in Redux applications
state.count = 1;
Copy the code

Instead, we create all the behaviors that a user might use in the application.

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

1.3 Reducer Explains the behavior and updates the status

The last architectural part is called Reduer, which, as a pure function, returns a new copy of the state based on the previous state and behavior.

  • ifincrementIf triggered, the value increasesstate.count
  • ifdecrementIs triggered, then reducestate.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:
      returnstate; }};Copy the code

1.4 There is no Redux yet

Did you notice that? So far we haven’t even touched the Redux library, we’ve just created some objects and functions, that’s why I call it “mostly protocol”, 90% of Redux applications don’t really need Redux.

2. Start implementing Redux

To use this architecture, we have to put it into a store, and we will implement just one function: createStore. The usage is as follows:

import { createStore } from 'redux'

const store = createStore(countReducer);

store.subscribe((a)= > {
  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 }
Copy the code

Here is our sample initialization code, and we need a list of listeners and reducer provided with the initialization status.

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

Whenever someone subscribes to our Store, they are added to the Listeners’ array. This is important because every time someone dispatches an action, all of the listeners need to be notified within the event cycle. Calling the yourReducer function with a undefined and an empty object will return an initialState, which is what we returned when we called store.getState(). With that said, let’s create this method.

2.1 store. GetState ()

This function is used to return the latest state from the store, which we need to update our view every time the user clicks a button.

const createStore = (yourReducer) = > {
    let listeners = [];
    let currentState = yourReducer(undefined{});return {
        getState: (a)= > currentState
    };
}
Copy the code

2.2 store. The dispatch ()

This function takes an action as its input and feeds this action and currentState back to yourReducer to get a new state, and the Dispatch method notifies every listener that subscribed to the current store.

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

      listeners.forEach((listener) = >{ listener(); }); }}; };Copy the code

2.3 store. The subscribe (the listener)

This method lets you be notified when the Store receives an action, calling store.getState() to get the latest status and update the UI.

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

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

      const unsubscribe = (a)= > {
        listeners = listeners.filter((l) = >l ! == newListener); };returnunsubscribe; }}; };Copy the code

Also, the SUBSCRIBE function returns another function, unsubscribe, which allows you to unsubscribe when you are no longer interested in store updates.

Clean up your code

Now let’s add the button logic and look at the final source code:

// Simplified createStore function
const createStore = (yourReducer) = > {
  let listeners = [];
  let currentState = yourReducer(undefined{});return {
    getState: (a)= > currentState,
    dispatch: (action) = > {
      currentState = yourReducer(currentState, action);

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

      const unsubscribe = (a)= > {
        listeners = listeners.filter((l) = >l ! == newListener); };returnunsubscribe; }}; };// Architectural components of Redux
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:
      returnstate; }};const store = createStore(countReducer);

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

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

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

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

// Follow the new UI when distributing actions
store.subscribe((a)= > {
  const state = store.getState();

  counterDisplay.innerHTML = parseInt(state.count);
});
Copy the code

Let’s look at the final view again:

Original: www.freecodecamp.org/news/redux-…

4. Communication

This article will briefly take a look at the three architectural components of Redux and how to implement a simplified version of Redux. We hope to have a further understanding of Redux and discuss the technology with you.

The article has been updated toMaking a blog, if your article is ok, welcome to STAR!

One of your likes is worth more effort!

Grow up in adversity, only continue to learn, to become a better yourself, with you!