So, what is React Redux?
In React if any information needs to be passed between components then I have seen most developers implement it in the form of Props. Passing props from Parent component to all the way to all the child components. This is a disaster bubble waiting to be broken. This way of passing information between components is called “Props Drilling”. To avoid this challenge of “Props Drilling”, we will be using Redux with React. Redux with React will be acting as a single source of truth for React application. The purpose of this post is to guide you with a simple example of how to integrate Redux with React easily. You can follow the same process for integration Redux with React native application. If you are new to React then read – React.js tutorial for beginners in 10 mins We will be working on a similar example of Amazon store as we did in the post – Learn what is redux Our final output should something like belowCreate react app
I have created the app “react-redux-tutorial” using below command.npx create-react-app react-redux-tutorial
Install Redux with React
cd react-redux-tutorial npm install redux react-redux
Folder Structure
I have added 3 folders called Components, Redux and Styles as below.
Define Constants
I like to define the constants used in the react redux tutorial example as below. I have created the file StoreActionConstants.js inside the Redux folder. Copy the below content into the file. I am not defining what the constants are as the names are giving away the meaning already.export const BUY_SHIRT = 'BUY_SHIRT' export const BUY_PANT = 'BUY_PANT' export const INITIAL_INVENTORY_SHIRTS = { numOfShirts : 100 } export const INITIAL_INVENTORY_PANTS = { numOfPants : 100 }
Define STAR (Store, Action, Reducer)
Define Action
The next step is to define the actions we will be needing to Buy Pant or Buy Shirt. I have created the file StoreActions.js inside Redux folder. Copy the content from below.import { BUY_SHIRT,BUY_PANT } from "./StoreActionConstants" export const buyShirt = () =>{ return{ type:BUY_SHIRT } } export const buyPant = () =>{ return{ type:BUY_PANT } }
Define Reducer
We will define the actions to perform on click of Buy Shirt or Buy Pant. I have imported the constants and the initial inventory constants as well. The last post on Learn what is Redux was using only one reducer. This time I have defined two reducers and I am combining them using “combineReducers“. Copy the code to the file StoreReducers.js inside the Redux folder.import {BUY_SHIRT, BUY_PANT, INITIAL_INVENTORY_SHIRTS, INITIAL_INVENTORY_PANTS } from "./StoreActionConstants" import { combineReducers} from 'redux' //INITIAL_INVENTORY is the initial value const buyShirtReducer = (state=INITIAL_INVENTORY_SHIRTS,action)=>{ switch(action.type){ case BUY_SHIRT: return{ ...state, numOfShirts:state.numOfShirts-1 } default: return state; } } const buyPantReducer = (state=INITIAL_INVENTORY_PANTS,action)=>{ switch(action.type){ case BUY_PANT: return{ ...state, numOfPants:state.numOfPants-1 } default: return state; } } const rootReducer = combineReducers({ shirt : buyShirtReducer, pant : buyPantReducer }) export default rootReducer;
Defining the Store
Now let us define the soul of redux.
Image by Okan Caliskan from Pixabay
import {createStore} from 'redux' import rootReducer from './StoreReducers' const AmazonStore=createStore(rootReducer) export default AmazonStore;
Defining the UI components
I have tried to use the Separation of Concern principle to show how effectively Redux can be used. I have created 3 components. In all the 3 UI components I have imported ‘connect’ function from ‘react-redux’. React Redux connect function allows the components to connect to the Redux store. I have implemented two functions mapStateToProps and mapDispatchToProps. These functions are passed to the connect function and Redux passes the state and the actions through this method.Buy Shirt – On click of buy will reduce the count of shirts for the initial inventory count.
import React from 'react'; import {connect} from 'react-redux' import {buyShirt} from '../Redux/StoreActions' function BuyShirt(props) { return ( <div className="button-container"> <button onClick={props.buyShirt}>Buy Shirt</button> </div> ); } // Calling only mapDispatchToProps as mapStateToProps is not needed here const mapDispatchToProps = dispatch =>{ return { buyShirt: ()=> dispatch(buyShirt()) } } export default connect(null,mapDispatchToProps) (BuyShirt);
Buy Pant – On click of buy will reduce the count of pants the initial inventory count
import React from 'react'; import {connect} from 'react-redux' import {buyPant} from '../Redux/StoreActions' function BuyPant(props) { return ( <div> <button onClick={props.buyPant}>Buy Pant</button> </div> ); } // Calling only mapDispatchToProps as mapStateToProps is not needed here const mapDispatchToProps = dispatch =>{ return { buyPant: ()=> dispatch(buyPant()) } } export default connect(null,mapDispatchToProps) (BuyPant);
Inventory – This component pulls the data from the Redux state and populates it accordingly.
import React from 'react'; import {connect} from 'react-redux' function Inventory(props) { return ( <div className="inventory-container"> <h1>Total Inventory</h1> <p>Number of shirts is - {props.numOfShirts}</p> <p>Number of pants is - {props.numOfPants}</p> </div> ); } // Calling only mapStateToProps as mapDispatchToProps is not needed here const mapStateToProps = state =>{ return{ numOfShirts : state.shirt.numOfShirts, numOfPants : state.pant.numOfPants } } export default connect(mapStateToProps,null) (Inventory);None of the components know how they are communicating with each other. Redux is the only point of contact for the information processing.
Final product
Now, let us assemble all the components in the App.js as below. We have imported the AmazonStore and have the Provider know which Redux store it should be consuming by Provider store={AmazonStore}import React from 'react'; import './App.css'; import './Styles/styles.css'; //Import Redux components import {Provider } from 'react-redux' import AmazonStore from './Redux/AmazonStore' //Import all components import Inventory from './Components/Inventory' import BuyShirt from './Components/BuyShirt' import BuyPant from './Components/BuyPant' function App() { return ( <Provider store={AmazonStore}> <div className="App"> <BuyShirt/> <BuyPant/> <Inventory/> </div> </Provider> ); } export default App;I have defined a Styles.css which is optional and I just defined it for styling all the components in one place.