Implementing Redux Architecture using React-Hooks

Building a Todo app with React Hooks

React, one of the best libraries to build front-end web applications. A lot has changed over few years with React library. The latest version of React i.e., 16.8 introduces a new concept of Hooks. This, gives a better way to write components in React. React was always down seen because it wasn’t a full blown framework and it lacked state management. With some of the features of hooks like useContext(), createContext(), useState() and useReducer() the state management problem of React is finally solved. No need to install a third party library to achieve and manage state.

If you have worked with Redux(A state management) library then learning to manage the state with React hooks will be very simple. For this, we need to go back to the basics of React-Redux architecture.

React-Redux Architecture

We need Three main components as usual to setup our boiler plate for React-Redux app.

Store: Single source of truth. Action functions: functions which dispatch actions with type and payload. Reducers: A function which catches the action and manipulates the Store depending on the action.

Let’s create an application to better understand the concept. We will be creating a todo application.

Todo App with React-Hooks:

Start the project using the create-react-app CLI tool.

If you get stuck anywhere in between. You can use the Github link to verify your code.

Github: https://github.com/akshayjp123/todo-with-react-hooks

$ create-react-app todo-app

Now, let’s create a file Store.js in src/ folder. Create a store using the createContext() hook in Store.js:

import React from "react"; export const Store = React.createContext();

Now, let’s start creating the reducer for our store. As usual each reducer will need an initial state, similar to our redux reducers. And a function which will accept initial state and action as input. Lets, create that in our Store.js:

const initialState = {

todos: [];

} function reducer(state, action){ switch(action.type){ case 'PUT_DATA':

let old_todos = state.todos;

old_todos.push(action.payload);

return { ...state, todos: old_todos } case 'DONE_TODO':

const index = action.payload;

let current_todos = state.todos;

current_todos.splice(index,1);

return { ...state, todos: current_todos } default:

return state;

}

}

Let’s create a store provider in our Store.js which will act as our Provider in Redux. So that we will be able to server Store all over the app.

export function StoreProvider(props) {

const [state, dispatch] = React.useReducer(reducer, initialState)

const value = {state, dispatch}

return <Store.Provider value={value}>{props.children} </Store.Provider>

}

import store provider from Store.js into your index.js:

import { StoreProvider } from "./Store.js";

Apply the provider around the <App/> within the ReactDOM.render of index.js:

ReactDOM.render(<StoreProvider><App /></StoreProvider>, document.getElementById('root'));

Now that we have all the setup, all we have to do now is to build the components.

Let’s see how we can make the store available to the components and how to dispatch actions to our reducer.

First, make the store available to component. Delete everything in App.js and write the below code:

import { Store } from "./Store"; export default function App() {

const { state, dispatch } = React.useContext(Store);

const [ todo, setTodo ] = React.useState("") //adding todo dispatch action

const putData = (e) => {

e.preventDefault()

return dispatch({

type: 'PUT_DATA',

payload: todo

})

} //deleting todo dispatch action

const doneTodo = (index) => {

return dispatch({

type: 'DONE_TODO',

payload: index

})

} }

In the above code you can see how we have mapped our state and dispatch to be used within our component. Thanks to useContext() ! and we have one local state to hold all our component local data.

Next, we have two action functions putData() and doneTodo() which will dispatch actions with type and payload. Very similar to our React-Redux

All thats left now is a return() content to display all of our content. Add a return right below the action functions:

import { Store } from "./Store"; export default function App() {

const { state, dispatch } = React.useContext(Store);

const [ todo, setTodo ] = React.useState("") //adding todo dispatch action

const putData = (e) => {

e.preventDefault()

return dispatch({

type: 'PUT_DATA',

payload: todo

})

} //deleting todo dispatch action

const doneTodo = (index) => {

return dispatch({

type: 'DONE_TODO',

payload: index

})

} return (

<React.Fragment>

<div className="App">

<form id="form">

<input id="todo_input" type="text" placeholder="Todo" onChange={(e)=> setTodo(e.target.value)}></input><br/>

<button id="submit_button" type="submit" onClick={(e) => putData(e)}>Add</button>

</form>

<h1>Tasks for Today</h1>

<ul className="todo_list">

{state.todos.map((item,index)=>(

<li className="todo_item" value={index} key={index} onClick={(e) => doneTodo(e.target.value)}><h3>{item}</h3></li>

))}

</ul>

</div>

</React.Fragment>

)

}

Add some styling to the App according to your will, I have given a sample CSS below for App.css:

.App {

text-align: center;

} .App-logo {

animation: App-logo-spin infinite 20s linear;

height: 40vmin;

pointer-events: none;

} .App-header {

background-color: #282c34;

min-height: 100vh;

display: flex;

flex-direction: column;

align-items: center;

justify-content: center;

font-size: calc(10px + 2vmin);

color: white;

} .App-link {

color: #61dafb;

} @keyframes App-logo-spin {

from {

transform: rotate(0deg);

}

to {

transform: rotate(360deg);

}

} #form {

background-color: #e0e0e0;

padding: 40px;

} #todo_input {

width: 80%;

height: 40px;

border: none;

font-size: 20px;

} #submit_button {

width: 80px;

height: 40px;

margin: 10px;

border: none;

box-shadow: 5px 5px 5px #888888;

font-size: 20px;

border-radius: 40px;

} #submit_button:hover {

box-shadow: 2px 2px 5px #888888;

background-color: #80cbc4;

color: white;

} .todo_list {

list-style-type: none;

padding-left: 0;

} .todo_item {

background-color: #282c34;

color: wheat;

margin: 20px;

padding: 20px;

}

Go ahead and fire up the local server to see how our app looks right now.

$ npm start

todo app

Conclusion:

React has evolved into a very powerful library in 2019. With all the features of a framework, React is a library used to create static web pages. It has a lot of advantages over a full blown web framework and I am sure there are a lot of features coming up soon which will make usage of React for developers even more easier.

Thats all folks, Thank you!