React Flux Concepts

Flux is a concept where the data-flow is one-way or unidirectional or so-called top-down or parent-child. The data flows from the top component down to children components. A React implementation of this is Redux.

There are four parts to this concept:

  1. Actions: Actions are sent through a dispatcher to trigger data flow
  2. Dispatcher: This is the center of the app, data is dispatched and sent to the store
  3. Store: This is the area where all the application state and /logic is held
  4. Controller View: This receives data and renders it

Advantages of flux

  • The app is easy to maintain
  • The data flow is one-way
  • It is easier to debug and check for errors.

ACTION  >>  DISPATCHER  >>  STORE  >> VIEW

Explaining Redux

A close enough example is the layout of Redux. It consists of a dispatcher or reducer that sends a particular action to a store and the corresponding changes are then made. In this lesson, we will see how to order a doughnut in a store by dispatching an action BUY_DOUGHNUT.

To get started with Redux, input the following commands:

npm init –yes

npm install redux react-redux

The first command installs prepare our project for new dependencies and the second install redux.

In a new folder, create a new file, we will call it orders.js. In this file we will define the state of our doughnut store, an action for buying a doughnut then a reducer that dispatches that action.

Creating State

First, initialize a state, let’s say the number of doughnuts is 10:

initialState = {
   numOfDoughnuts = 10
}

Actions

We now define an action that allows us to order a doughnut:

{
   type : BUY_DOUGHNUT,
}

Or in form of a function, called an action creator that only returns the action:

initialState = {
   numOfDoughnuts = 10
}

function buyDoughnut() {
   return {
      type : BUY_DOUGHNUT,
   }
}

Reducers

Now we define a reducer that checks if we triggered an action type of BUY_DOUGNUT, and if so actually reduce the state or number of the doughnuts, a reducer is a pure function that takes in a state and returns the next state:

const reducer = (state= initialState, action) => {
   switch (action.type) {
      case 'BUY_DOUGHNUT':
            return { ...state,
                      numOfDoughnuts: state.numOfDoughnuts - 1
               }
      default:
         return state;
   }
}

So we defined a switch statement that checks the action. If the type of action is BUY_DOUGHNUT, it reduces the state by one else it just returns the original state.

Connecting with Redux

Now we connect the reducer to redux so as to take effect. To do this we pass in the reducer function to a redux function known as createStore.

import {createStore} from 'redux'

Then the full code looks like this:

import {createStore} from 'redux'

initialState = {
   numOfDoughnuts = 10
}

function buyDoughnut() {
   return {
      type : 'BUY_DOUGHNUT',
   }
}

const reducer = (state= initialState, action) => {
   switch (action.type) {
      case 'BUY_DOUGHNUT':
            return { ...state,
                      numOfDoughnuts: state.numOfDoughnuts - 1
               }
      default:
         return state;
   }
}

const store = createStore(reducer)

Dispatch Actions

To dispatch an action to the store we simply write:

store.dispatch(buyDoughnut())

we pass in the action creator to the store. To check if our action had an effect on  the store we add a listener that logs a content anytime the store is changed.

store.dispatch(buyDoughnut())
store.subscribe(() => console.log('Updated store:', store.getState()))

Each time the store is changed, the subscribe() method logs the updated state of the store to the console. Full code:

import {createStore} from 'redux'

initialState = {
   numOfDoughnuts = 10
}

function buyDoughnut() {
   return {
      type : 'BUY_DOUGHNUT',
   }
}

const reducer = (state= initialState, action) => {
   switch (action.type) {
      case 'BUY_DOUGHNUT':
            return { ...state,
                      numOfDoughnuts: state.numOfDoughnuts - 1
               }
      default:
         return state;
   }
}

const store = createStore(reducer)

store.dispatch(buyDoughnut())
store.subscribe(() => console.log('Updated store:', store.getState()))

To view, in your command-line navigate to the folder and then input ‘node store.js’. e.g.

C:\Users\HP\newfolder> node store.js

You can dispatch as many times as you want:

store.dispatch(buyDoughnut())

store.dispatch(buyDoughnut())

store.dispatch(buyDoughnut())

store.dispatch(buyDoughnut())

store.dispatch(buyDoughnut())

store.subscribe(() => console.log('Updated store:', store.getState()))

In a react project, it will be smarter to separate the reducer, actions, and store into separate files and then import each of the required components when needed.