Skip to main content

React Redux Tutorials: React Redux Data Flow and Redux Lifecycle Methods With Examples

React Redux Data Flow and Redux Lifecycle Methods Overview

What is Redux and why do we need Redux

Redux is an open source JavaScript library which is designed for maintaining application state. Redux JS is a powerful and popular library nowadays. The command to install Redux library npm install redux --save.
Nowadays JavaScript single-page applications are very popular and powerful. As the requirements for single-page applications have become complicated, our code must manage more state than ever before. This state can include server responses and cached data, as well as locally generated data that has not yet been persisted to the server. Front-end state is also increasing in complexity, as we need to manage active routes, selected tab, spinners, pagination controls etc. That's why we need Redux.
click here to learn React Redux Architecture, folder structure.

Three Principles of Redux:
  • Changes are made with pure functions
  • You write pure reducers to specify how the state tree is transformed by actions.Reducers are just pure functions that take the previous state and an action, and return the next state.Keep remembering to return always new state objects, instead of mutating the previous state.
    import { combineReducers, createStore } from "redux";
    const initialState = {    
        text: "",
        completed: false  
    };
    function toggleReducer(state = initialState , action) {
      switch (action.type) {
        case "TOGGLE":
          return {
            ...state,
            completed: !action.completed
          };
        default:
          return state;
      }
    }
    
    function todosReducer(state = initialState , action) {
      switch (action.type) {
        case "ADD_TODO":
          return [
            ...state,
             {
              text: action.text,
              completed: false
            }
          ];
        case "COMPLETE_TODO":
          return state.map((todo, index) => {
            if (index === action.index) {
              return {
                ...state,
                todos: {
                  completed: true
                }
              };
            }
          });
        default:
          return state;
      }
    }
    const rootReducer = combineReducers({ toggleReducer, todosReducer });
    const store = createStore(rootReducer);
    
  • State is read-only
  • The only way to change the state is to emit an action, an object describing what happened. This ensures that neither the views nor the network callbacks will ever write directly to the state. Instead, they express an intent to transform the state. Because all changes are centralized and happen one by one in a strict order, there are no subtle race conditions to watch out for. As actions are just plain objects, they can be logged, serialized, stored, and later replayed for debugging or testing purposes.
  • Single source of truth
  • The state of your whole application is stored in an object tree within a single store. This makes it easy to create universal apps, as the state from your server can be serialized and hydrated into the client with no extra coding effort. A single state tree also makes it easier to debug or inspect an application, it also enables you to persist your app's state in development,for a faster development cycle.
    Click here to learn React JS Component lifecycle methods. 

React Redux Data Flow and Redux Lifecycle Methods:

Basic Redux Data Flow and Lifecycle:
Redux flow diagram

Here, react component calls action creator, action creator returns an action, action sends information to the reducer, reducer creates a new state and that state sends to react component.

React Views
React Container component connect with Store to get the updated state or data. Map state to props (MapStateToProps), connected components specify what state they want as props. Container component dispatch an action.

Action Handlers 
Most business logic and side effects are implemented here. This is the right place to handle the actions. Redux thunk and Redux Saga are the middleware to call the API. We'll discuss later about Redux Saga.

Store
Store holds the global app state, allows access to state via getState(), allows state to be updated via dispatch(action) and registered listener via subscribe(listener).

Redux JS Lifecycle Methods

Actions 

Action is payload of information that send data from your application to your store. They are the only source of information for the store. You can send them to the store using store.dispatch() or using react redux connect.
Action must have a type property that indicates the type of action being performed. Types should typically be defined as string constants.
//types
const ADD_ITEM = 'ADD_ITEM'
//object
{
  type: ADD_ITEM,
  text: 'Item'
}

Action Creators :Action Creators are functions which create an actions,It returns an action.
Redux JS Action Creators Example
types.js
const ADD_ITEM='ADD_ITEM';
const REMOVE_ITEM='REMOVE_ITEM';
export{
    ADD_ITEM,
    REMOVE_ITEM
}
actions.js
import * as types from "./types";

const addItem = payload => {
  type: types.ADD_ITEM, payload;
  meta: {
    key: 'addItem'
  }
};

const removeItem = (payload) => {
  type: types.REMOVE_ITEM, 
  payload;
  meta: {
    key: 'removeItem'
  }
};

export{
    addItem,
    removeItem
}
Actions Creators: dispatch() and connect() are the functions used to actions creators.
you can call function mapDispatchToProps() that receives the dispatch() method and returns callback props that you want to inject into the presentational component.
Redux JS Selector :selector is a layer in which we can modify store accordingly. This is good place to filtering and sorting the data.
selectors.js
export const getTodos=(state)=>state.todos;
container.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { addItem, removeItem } from "./actions";
import Todos from "./Todos";
import {getTodos} from './selectors';

class TodoContainer extends Component {
  constructor(props) {
    super(props);
    this.handleAddItem = this.handleAddItem.bind(this);
    this.handleRemoveItem = this.handleRemoveItem.bind(this);
  }

  handleAddItem(todo) {
    this.props.onAddItem(todo);
  }

  handleRemoveItem(id) {
    this.props.onRemoveItem(id);
  }

  render() {
    const { todos } = this.props;
    return (
      <Todos
        todos={todos}
        onAddItem={this.handleAddItem}
        onRemoveItem={this.handleRemoveItem}
      />
    );
  }
}

const mapStateToProps = state => {
  return {
    todos: getTodos(state)
  };
};

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onAddItem: todo => {
      dispatch(addItem(todo));
    },
    onRemoveItem: id => {
      dispatch(removeItem(id));
    }
  };
};

//with mapDispatchToProps
const enhance = connect(mapStateToProps, mapDispatchToProps);

//without mapDispatchToProps
const enhance = connect(mapStateToProps, {
  onAddItem: addItem,
  onRemoveItem: removeItem
});

export default enhance(TodoContainer);

Reducers 
The reducer is a pure function that takes the previous state and an action, and returns the next state. Reducers specify how the application's state changes in response to actions sent to the store. Remember that actions only describe the fact that something happened, but don't describe how the application's state changes. NPM command to install react redux package npm install --save react-redux
reducers.js
const initialState = {
  todos: [],
  id: "",
  text: ""
};

const todos = (state = initialState, action) => {
  switch (action.type) {
    case "ADD_ITEM":
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ];
    case "REMOVE_ITEM":
      return {
        ...state,
        id: action.id
      };
    default:
      return state;
  }
};

export default todos;

Create store and connect with React JS :
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import todos from './reducers'
import Root from './components/Root'

let store = createStore(todos)

render(
  <Root store={store} />,
  document.getElementById('root')
)

Redux Middleware

Redux thunk and Redux Saga are the middlewares . Nowadays React Redux developer followed Redux Saga which is very popular. Redux Saga : redux-saga is a redux middleware, which means this thread can be started, paused and cancelled from the main application with normal redux actions, it has access to the full redux application state and it can dispatch redux actions as well. I'll explain redux-saga in details in separate post.
sagas.js
import { delay } from "redux-saga";
import { fork, call, put, takeLatest } from "redux-saga/effects";
import api from "./api";
import { receiveData } from "./actions";
import * as types from "./types";

function* fetchResource() {
  const { data } = yield call(api.fetchData);
  yield put(receiveData(data));
}

function* watchFetchResource() {
  yield takeLatest(types.FETCH_RESOURCE, fetchResource);
}

export function* rootSaga() {
  yield [fork(watchFetchResource)];
}
Connect Redux-Saga:
import React from 'react';
import { render } from 'react-dom'
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import rootSaga from './sagas'

const sagaMiddleware = createSagaMiddleware()
const store = createStore(
  reducer,
  applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(rootSaga);
render(
  <Root store={store} />,
  document.getElementById('root')
)

Here, we learned react redux data flow, redux lifecycle methods, how they are connected to each other. Explained middleware redux saga, how to connect redux saga with react.

Comments

  1. It was nice explaination of react and redux saga.Thank you so much.

    ReplyDelete

Post a Comment

Thanks for visiting blog. Have a good day.

Popular posts from this blog

React Redux Application Structure, Architecture and React Folder Structure Best Practices

React Redux Application Structure, Architecture and  React Folder Structure Best Practices: There some questions comes our mind when we are going to create a new react redux application structure from scratch. What folder structure should be followed especially when we are implementing a large react redux application . How to connect react with redux  What should be the naming convention of folder and react js files. What are the best practices of react redux project structure. The structure might be different for each of us but I am sharing the standard react redux application structure which is followed by most of the UI developers in IT industry. High Level React Redux Application Architecture There are many folders and files in above application screen shot, let discuss one by one. The application name is REACTWEBAPP and folders are config, public, script, server, src, reducers, sagas, store and package.json. Config: react redux application configurations

ReactJS Routing And Single Page Application Tutorial

React Router: ReactJS Single Page Application Why do we need React Router Nowadays single page application is the most popular. For making single page application, we need to react router. Single page application is very powerful and provides performance features as well. What is React Router React router is a library, it provides routing feature through which we can redirect from one page to another page. Mainly there are two types of routing. 1. Browser Specific routing: In general or e-commerce web application have browser routing and it helps in search engine optimization. npm command to install routing package npm install react-router --save . --save is used to save the package entry in project specific package.json file. import React from 'react'; import ReactDOM from "react-dom"; import { Router, Route, Link, browserHistory, IndexRoute } from 'react-router'; import Home from './Home'; import About from './About'; import