Image for post
Image for post

📄 Table of contents

◉ What is Redux?

Redux is a predictable state container for JavaScript and comes as an external library which can be used together with front-end frameworks like React, Angular, Ember.js, Backbone etc. However Redux is most often used together with React.

Redux is very lightweight measuring only 2KB.

In React, data flows from parent component to child component in the form of props. In react mostly everything is component, so if there are too many number of components, here comes the role of redux as it manages the states of all components.

The Problem With Traditional MVC Architecture

Before diving deeper into the concepts of Redux let’s first focus on the problems it solves. The Model-View-Controller (MVC) pattern is familar to most front-end web developers nowadays. This pattern describes a separation between the data (model), the presentation (view) and the application logic (controller). This ensures that your application is built in a structured way and that you achieve a separation of concerns.

However the disadvantage is that you’re loosing control of your data flow. In general the data flow is bi-directional. The user input in one component can affect other components and vice versa. Controlling the flow of data and making sure that all user interface components update accordingly is an error-prone task.

How State Management Solves The Problem

By using Redux we’re solving this problems by introducing a central data store in our application. The store contains the state of the application and is the source of truth for components. By using the store concept you do not need to synchronize state between components manually. Instead you can fully rely on the Redux store at any time.

Building Blocks Of Redux

The working principle of Redux is quite simple and straightforward. Redux can be considered as a central store which holds the entire state of the application. Each of its components can access the given stored state without requiring sending down property from one component to another.

The key points of interest while working with redux are as below:

[1]. Action

Actions are used to send information from the application to the store. Sending information to the store is needed to change the application state after a user interaction, internal events or API calls.

Actions are JavaScript objects as you can see in the following example:

{
type: LOGIN_USER,
payload: {username: ‘sebastian’, password: ‘123456’}
}

Action objects are created by using functions. These functions are called action creators:

function authUser(data) {
return {
type: LOGIN_USER,
payload: data
}
}

Here you can see that the only purpose of an action creator function is to return the action object as described.

[2]. Dispatcher ->collects the action that is actively triggered and passes it to reducer.

Calling actions in the application is easy by using the dispatch method:

dispatch(authUser(data));

[2.5] middleware -> extend the functionality of our redux application.

[3]. Reducers

Reducers are pure JavaScript functions that take the current application state and an action object and return a new application state:

function myReducer (state , action)  {
switch (action.type) {
case 'LOGIN_USER':
return Object.assign({}, state, {
auth: action.payload
})
default:
return state
}
}

The important thing to notice here is that the state is not changed directly. Instead a new state object (based on the old state) is created and the update is done to the new state.

[4]. Store -> which holds our state (single source of data).

The store is the central objects that holds the state of the application. The store is created by using the createStore method from the Redux library:

import { createStore } from ‘redux’;
let store = createStore(myReducer);

You need to pass in the reducer function as a parameter. Now you’re ready to disptach a action to the store which is handled by the reducer:

let authData = {username: ‘sebastian’, password: ‘123456’};
store.dispatch(authUser(authData));
Image for post
Image for post

for more…watch this video tutorial https://egghead.io/courses/getting-started-with-redux to have an understanding of Redux.

Simplest working example of react along with redux:

◉ Basic Redux Setup

Image for post
Image for post
Minimal Redux BareBone setup
Image for post
Image for post
Counter Container Component

◉ Middleware in React/Redux

source: https://blog.jakoblind.no/redux-ajax-best-practices/

Redux also provides us with a middleware, this middleware are functions that allow us extend the functionality of our redux application. The middleware sits in between the dispatch and reducers, which means we can alter our dispatched actions before they get to the reducers or execute some code during the dispatch.

The three most widely used and stable Redux Ajax middleware are:

  1. Redux Promise Middleware
  2. Redux Thunk Middleware
  3. Redux Saga Middleware

An example of a redux middleware is redux-thunk which allows you to write action creators that return a function instead of the typical action (object).

This is the standard way of doing Ajax with Redux.

When using Redux Thunk, your action creators returns a function that takes one argument dispatch:

function getUserName(userId) {
return dispatch => {
return fetch(`/api/personalDetails/${userId}`)
.then(response => response.json())
.then(json => dispatch({ type: "SET_USERNAME", userName: json.userName })
}
}

dispatch is a function that dispatches an action. The action creator can call dispatch inside .then to execute it asynchronously. The action creator can call dispatch as many time as it wants.

When to use

  • You make many Ajax calls in one action, and need to dispatch many actions
  • You require full control of the format of your actions

◉ Creating custom Middleware in React/Redux.

In this article i would be showing how you can build your own custom middleware.

Image for post
Image for post
Redux library, and it’s modules.

Writing a middleware is very easy, and below is a basic code to create your middleware.

const customMiddleware = store => next => action => {
...
}

Above means our middleware receives a store, then returns a function that receives a next function and returns another function that receives an action.

As you can see, the middleware is a curried function.

What is a curried function? A curried function is a function that returns another function.

Example:

const foo = a => b => a + b;
foo(1)(2); //=> 3
OR in ES5function foo(a) {
return function(b) {
return a + b;
}
}

The Store: That’s our redux store.

The Next: We call this function when our middleware is done with the task assigned to do. This sends our actions to our reducer or another middleware.

The Action: Thats our action currently being dispatched.

Now let’s write some code:

I have forked the react-redux repo to quickly help us get started with writing code, and i would be working with the counter example.

To apply a middleware in redux, we would need to require the applyMiddleware function from the redux library.

import {createStore, applyMiddleware} from "redux";

In order to check that our middleware is hooked up correctly, we can start by adding a log to display a message when an action is dispatched.

Image for post
Image for post

Now if we go ahead to trigger an action by clicking a button, we would see the logged message in our console.

Image for post
Image for post
On dispatch, middlewares are triggered.

In our middleware we have access to store.getState() to get the current state and store.dispatch() to dispatch a new action if we want to.

Next we can add another middleware to trigger an event when we click the increment button.

Image for post
Image for post

Easy as pie! isn’t it.

An exercise you can try out: Display a loader icon when your actions make request to your backend to process data and clear the loader icon when data gets to your reducers.

References: https://medium.com/netscape/creating-custom-middleware-in-react-redux-961570459ecb

Redux-Thunk vs. Redux-Saga

source:https://medium.com/@shoshanarosenfield/redux-thunk-vs-redux-saga-93fe82878b2d

While building my first basic CRUD (create, read, update and delete) application, I was stumped as to how to integrate my axios data request into a Redux action creator. How do I bake in this layer of asynchronous code and feed the data to my Redux store? After researching, I found Redux-Thunk middleware to be a possible solution. This super helpful middleware allowed me to write an intermediary function, a thunk, that would make the ajax request and then call the action creator using the data received in the response of the object. As I continued to read other articles, I found that this was only one solution of several middleware options available.

But why a middleware is required ?

The reason that we need to use a middleware such as Redux-Thunk is because the Redux store only supports synchronous data flow. Hence, to support Asynchronous(-ity), middleware(s) comes to the rescue!

Middleware allows for asynchronous data flow, interprets anything that you dispatch and finally returns a plain object allowing the synchronous Redux data flow to resume. Redux middleware can thus solve for many critical asynchronous needs (e.g., axios requests).

Redux-thunk

To begin, what is a thunk?

A thunk is a function that acts as a wrapper in that it wraps an expression to delay its evaluation.

For example, in the below code, the foo function acts as a thunk as it delays the calculation of the mathematical expression, 1 + 2.

Image for post
Image for post

According to Eric Raymond, the inventors of the thunk coined the term “after they realized (in the wee hours after hours of discussion) that the type of an argument in Algol-60 could be figured out in advance with a little compile-time thought […] In other words, it had ‘already been thought of’; thus it was christened a thunk, which is ‘the past tense of “think” at two in the morning”.

In the context of Redux, Redux-Thunk middleware allows you to write action creators that return a function instead of the typical action object. The thunk can then be used to delay the dispatch of an action until the fulfillment of an asynchronous line of code (e.g., an axios request to receive data).

Below is an outline of the step-by-step process of Redux-Thunk:

1.If it is a regular action object, Redux-Thunk does not do anything and the action object is processed by the store’s reducer.

2. If the action is a function, Redux-Thunk invokes it and passes it the store’s dispatch and getState methods and any extra arguments (e.g., axios)

3. After the function runs, the thunk then dispatches the action, which will then update the state accordingly.

Image for post
Image for post

Thus, in summary there are two parts to Redux-Thunk:

  1. A thunk creator, which is an action creator that returns a thunk (a.k.a. asynchronous action creators)
  2. The thunk itself, which is the function that is returned from the thunk creator and accepts dispatch and setState as arguments

Below is a graph of the npm downloads, over the past six months, for these other middleware options.

The other most commonly used middleware is Redux-Saga.

Redux-Saga

First, to understand redux-saga you need to understand how Generators work in Javascript.

How redux-saga works ?

Redux-Saga is a library that aims to make application side effects (e.g., asynchronous actions such as fetching data) easier to handle and more efficient to execute.

Now coming to the project, we need to create to create actions, reducers and store for both redux-thunk and redux-saga. So in terms of configuration, pretty much entire code is same. Just the action part in redux-saga becomes really simple when generators kick in making redundant code of dispatches obsolete.

The idea is that a saga is similar to a separate thread in your application that’s solely responsible for side effects.

However, unlike Redux-Thunk, which utilizes callback functions, a Redux-Saga thread can be started, paused and cancelled from the main application with normal Redux actions. Like Redux-Thunk, Redux-Saga has access to the full Redux application state and it can dispatch Redux actions as well.

To do this, Redux-Saga utilizes a new ES6 feature called generators. Generators are functions which can be exited and later re-entered.

Image for post
Image for post

Simply calling a generator function, marked by the asterisk to the right of the function keyword, will not cause the body of the function to execute immediately. Instead an iterator object is returned (e.g., gen in the above example). When the iterator’s next method is invoked, the generator function’s body is executed up until the first yield (e.g., line 2 above). The iterator’s next method returns an object with a value property containing the yielded value and a done boolean property, which indicates whether the generator has yielded its last value.

But let’s take a step back. What is yield?

Line 2 above is called a ‘yield expression’ because when you restart the generator, you will send back in the value and it will be used as the newly evaluated value. In essence, the yield keyword makes a request for a value.

Unlike typical JavaScript functions, generator functions run through to completion. Generator functions can be ‘cooperative’, which is a function that chooses when it will allow an interruption, so that it can cooperate with other code. You can use the yield keyword to pause the function from inside of itself. Note that nothing can pause the generator from the outside. However, once paused the generator cannot restart itself. Only an external control can be used to restart the generator function.

So who wins? Redux-Thunk or Redux-Saga?

Neither. Below is the same example with the first version leveraging Redux-Thunk and the second Redux-Saga.

Image for post
Image for post
Redux thunk version
Image for post
Image for post
Redux-saga version

The benefit to Redux-Saga in comparison to Redux-Thunk is that

[1]. you can avoid callback hell meaning that you can avoid passing in functions and calling them inside.

[2]. Additionally, you can more easily test your asynchronous data flow. The call and put methods return JavaScript objects. Thus, you can simply test each value yielded by your saga function with an equality comparison. On the other hand, Redux-Thunk returns promises, which are more difficult to test. Testing thunks often requires complex mocking of the fetch api, axios requests, or other functions. With Redux-Saga, you do not need to mock functions wrapped with effects. This makes tests clean, readable and easier to write.

[3]. Redux-Thunk, however is great for small use cases and for beginners. The thunks’ logic is all contained inside of the function. Additionally, you do not need to learn a new function type, generators, and the keywords and methods associated with this function type. In conclusion, there are tradeoffs for each middleware and depending on your project, you can decide which middleware is most fitting for your code.

Now if you see we are able to pass the promises to redux-saga middleware and it handles it automatically. This is something I was looking forward to because it does not involved dispatch and redundancy of code goes down drastically.

source: https://tudip.com/blog-post/why-react-saga-is-better-then-thunk/

Middleware

Middleware is block of code which acts as a mediator while the process of receiving a request or generating response. Here we are going to discuss about the 2 most popular libraries redux-thunk and redux-saga.

A thunk is a function that acts as a wrapper in which it wraps an expression to delay its evaluation. Thunk allows to write an action creators that return a function instead of the typical action object.

Where as redux-saga is a library that mainly focuses on easy handling of application side effects and more efficient for execution.

Redux-thunk

Thunk is a function which optionally takes some parameters and returns another function, it takes dispatch and getState functions and both of these are supplied by Redux Thunk middleware.

Here is the basic structure of Redux-thunk:-

export const thunkName = parameters => (dispatch, getState) => {
// You can write your application logic here
};

Example:

import axios from "axios";
import GET_LIST_API_URL from "../config";
const fetchList = () => {
return (dispatch) => {
axios.get(GET_LIST_API_URL)
.then((responseData) => {
dispatch(getList(responseData.list));
})
.catch((error) => {
console.log(error.message);
});
};
};
const getList = (payload) => {
return {
type: "GET_LIST",
payload
};
}
export {fetchList}

Redux-saga

It allows one to express complex logic functions as pure functions called sagas. From a testing point of view, pure functions are desirable because they are predictable and repeatable, making them relatively easy to test. Sagas are implemented by special functions called functions of the generator. These are an ES6 JavaScript new feature. Basically, everywhere you see a yield statement, execution jumps in and out of a generator. Think of a statement of yield as causing the generator to pause and return the value of yield. The caller can then resume the generator after the yield at the statement.

Example:

import axios from "axios";
import GET_LIST_API_URL from "../config";
import {call, put} from "redux-saga/effects";
const fetchList = () => {
return axios.get(GET_LIST_API_URL);
}
function* fetchList () {
try {
const responseData = yield call(getCharacters);
yield put({
type: "GET_LIST",
payload: responseData.list});
}
catch (error) {
console.log(error.message);
}
}
export {fetchList};

Conclusion

You might think that syntax is the biggest difference. Although it is true that thunks and sagas are quite different in writing and reasoning, there is something bigger. In response to an action, Thunks can never act. On the other hand, Redux-Saga subscribes to the store and can trigger a saga when some action is dispatched to run or continue.
From the above examples it is clear that react saga is a bit handy to use over react-thunk.

List of Redux Alternatives

[1]. MobX

[2]. Relay & GraphQL

However, Redux is known to be the most popular library for managing state across your React application.

Reducer Example

◉ Immutability in React

In a typical React application, the state is an object. (Redux makes use of an immutable object as the basis of an application’s store.) React’s reconciliation process determines if a component should re-render or if it needs a way to keep track of the changes.

In other words, if React can’t figure out that the state of a component has changed, then it will not not know to update the Virtual DOM.

Immutability, when enforced, makes it possible to keep track of those changes. This allows React to compare the old state of an object with it’s new state and re-render the component based on that difference.

This is why directly updating state in React is often discouraged:

this.state.username = "jamesdoe";   X(not recommended )

React will not be sure that the state has changed and is unable to re-render the component.

◉ Updating (Mutating) state

The state is meant to be immutable, meaning it shouldn’t be changed directly. To create an updated state, we can make use of Object.assign or opt for the spread operator.

Image for post
Image for post

Example 2:

let user = { name: "James Doe", location: "Lagos" }
let newUser = user;
user.location = "Abia";
console.log(newUser.location) // "Abia" (NOT what we expected)
Image for post
Image for post

Experience with Front-end Technologies and MERN / MEAN Stack. Working on all Major UI Frameworks like React, Angular.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store