Redux: The Fundamentals

Above is a graph that shows you how redux works. Let’s learn it from a real project

I will use Andrei Neagoie robofriend project as an example. Below is a starter template. We will use redux in this starter template

Create a file called constants.js under the src folder. The constants.js store the variable that we will use later.

1. Turn the redux action type into variable so that if there is any misspelling, we can detect it easily.

export const CHANGE_SEARCH_FIELD = "CHANGE_SEARCH_FIELD";export const REQUEST_ROBOTS_PENDING = "REQUEST_ROBOTS_PENDING";export const REQUEST_ROBOTS_SUCCESS = "REQUEST_ROBOTS_SUCCESS";export const REQUEST_ROBOTS_FAILED = "REQUEST_ROBOTS_FAILED";

2. Create a action.js filer under src folder and import the variables from the constants,js

import {CHANGE_SEARCH_FIELD,REQUEST_ROBOTS_PENDING,REQUEST_ROBOTS_FAILED,REQUEST_ROBOTS_SUCCESS,} from "./constants";

3. Set up the action function. Below is how a action function looks. It returns the action type and action payload. The action-type is normally uppercased

export const setSearchField = (text) => {return {type: CHANGE_SEARCH_FIELD,payload: text,};};

4. This is an action that handles ajax call. Remember it needs to return a function instead of an object

For an Ajax call, we normally have 3 states. Ajax call pending, Ajax call success & Ajax call fail

export const requestRobots = () => (dispatch) => {dispatch({ type: REQUEST_ROBOTS_PENDING });fetch("https://jsonplaceholder.typicode.com/users").then((response) => response.json()).then((data) => dispatch({ type: REQUEST_ROBOTS_SUCCESS, payload: data })).catch((error) =>dispatch({ type: REQUEST_ROBOTS_FAILED, payload: error }));};

5.Create a reducer.js under src folder. Import the constants.js and set up the initial state for the search field

import {CHANGE_SEARCH_FIELD,REQUEST_ROBOTS_FAILED,REQUEST_ROBOTS_SUCCESS,REQUEST_ROBOTS_PENDING,} from "./constants";const initialStateSearch = {searchField: "",};

6. Set up a reducer function to handle the incoming function. We usually use a switch statement to handle the incoming function

When the incoming action match the case, we return a new state

export const searchRobots = (state = initialStateSearch, action = {}) => {switch (action.type) {case CHANGE_SEARCH_FIELD:return { ...state, searchField: action.payload };default:return state;}};

7. Set up the initial state of the ajax call

const initialStateRobots = {isPending: false,robots: [],error: "",};

8. Set up the reducer function to handle the ajax call action

export const requestRobots = (state = initialStateRobots, action = {}) => {switch (action.type) {case REQUEST_ROBOTS_PENDING:return { ...state, isPending: true };case REQUEST_ROBOTS_SUCCESS:return { ...state, robots: action.payload, isPending: false };case REQUEST_ROBOTS_FAILED:return { ...state, error: action.payload, isPending: false };default:return state;}};

9. We go to the index.js and import the Provider from react-redux to provide the state to the react project

10. import the createStore, combineReducers, and applyMiddleware from redux

11. import thunkMiddleware from redux-thunk. This is a redux middleware to handle ajax call

12. import the reducer function from reducers.js

//9. import the Provider from react-redux to provide the state to the react projectimport { Provider } from "react-redux";//10. import the createStore, combineReducers, and applyMiddleware from reduximport { createStore, combineReducers, applyMiddleware } from "redux";//11. import thunkMiddleware from redux-thunk. This is a redux middleware to handle ajax callimport thunkMiddleware from "redux-thunk";//12. import the reducer function from reducers.js

13. Declare the rootReducer. P.S. combinereducer function accept an object only

14. Declare the store and apply the redux middleware

//13. Declare the rootReducer. P.S. combinereducer function accept an object onlyconst rootReducer = combineReducers({ searchRobots, requestRobots });//14. Declare the store and apply the redux middlewareconst store = createStore(rootReducer, applyMiddleware(thunkMiddleware));

15. Wrap the <App /> with a Provider and pass the store as props

ReactDOM.render(//15. Wrap the <App /> with a Provider and pass the store as props<Provider store={store}><App /></Provider>,document.getElementById("root"));registerServiceWorker();

16. We go to the app.js and import the connect function from react-redux to connect react and redux

17. import the action from action.js

import React, { Component } from "react";//16. import the connect function from react-redux to connect react and reduximport { connect } from "react-redux";import CardList from "../components/CardList";import SearchBox from "../components/SearchBox";import Scroll from "../components/Scroll";import "./App.css";//17. import the action from action.jsimport { setSearchField, requestRobots } from "../actions";

18. Use the connect function. It accepts 2 parameters. MapStateToProps is a function that tells redux which states you want to pass as props

mapDispatchToProps is a function that tells redux what action you want to pass as props to your react project

//18.Use the connect function. It accepts 2 parameter. MapStateToProps is a function that tell redux which states you want to pass as props// mapDispatchToProps is a function that tell redux what action you want to pass as props to your react projectexport default connect(mapStateToProps, mapDispatchToProps)(App);

19. Declare the mapStateToProps function. It tells redux what states you want to pass as props

Parameter state comes from index.js provider store state(rootReducers)

//19. Declare the mapStateToProps function. It tells redux what states you want to pass as props// parameter state comes from index.js provider store state(rootReducers)const mapStateToProps = (state) => {return {// searchRobots come from the reducer.jssearchField: state.searchRobots.searchField,isPending: state.requestRobots.isPending,robots: state.requestRobots.robots,error: state.requestRobots.error,};};

21. Use the action as props

22. Use the states as props

componentDidMount() {//21. Use the action as propsthis.props.onRequestRobots();}render() {//22. Use the states as propsconst { searchField, onSearchChange, robots, isPending } = this.props;const filteredRobots = robots.filter((robot) => {return robot.name.toLowerCase().includes(searchField.toLowerCase());});return isPending ? (<h1>Loading</h1>) : (<div className="tc"><h1 className="f1">RoboFriends</h1><SearchBox searchChange={onSearchChange} /><Scroll><CardList robots={filteredRobots} /></Scroll></div>);}}

This is how normally a developer applies redux in their react project without using the redux toolkit.

The end project is in the below:

https://github.com/tinkit2004/Redux_demo

--

--

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