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:
ACTION >> DISPATCHER >> STORE >> VIEW
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
}
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,
}
}
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.
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)
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.