CRUD Application in React.js with Redux and Hooks.

Vahid Akhtar
6 min readDec 24, 2020

--

In this article, we will see hooks redux crud application with a react-bootstrap framework having multiple features following:

  • Create React App
  • Add, Update using modal
  • Multiple checkboxes
  • Unit-testing
  • Styling with Sass

A new concept was introduced in React Hooks. Hooks are an alternative to classes. If you’ve used to React before, you’ll be familiar with functional components and class components.

Many of the features are available to class components— such as lifecycle methods and state which has not been available to functional components until now. Hooks supports all that functionality and more.

Here, we’ll create a CRUD app. It will have lists of books, and you’ll be able to add, update, or delete books. We’ll use State Hooks and Effect Hooks on functional components. If you miss anything along the way, check out the source of the completed project.

Create React App

Create React App is an officially supported way to create single-page React applications. It offers a modern build setup with no configuration.

npx create-react-app styled-hooks-redux-crud
cd styled-hooks-redux-crud
npm start

install required libraries

npm install redux react-redux react-bootstrap bootstrap react-toastify uuid react-icons node-sass@4.14.1

Initial Setup-

Let’s start off by clearing out all the files from the boilerplate that we don’t need. Delete everything from the /src folder exceptindex.js

In index.js, replace yours with below

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App/App";
ReactDOM.render(<h2>Hello</h2>, document.getElementById("root"));

Add below link inside the head of public/index.html

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"    integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous" />

create data.js

The first thing we’ll do is redux setup for the initial view of the page. Create a file named src\actions\crudActions.js

const LIST_ITEMS  = 'LIST_ITEMS';
import { listArray } from '../utils/data';
export const getItems = () => {
return {
type: LIST_ITEMS,
payload: listArray
}
};

src\reducers\crudReducer.js

const LIST_ITEMS = 'LIST_ITEMS';
let initialState = {
lists: [], item: {}
};
export default function rootReducer(state = initialState, action) {
switch(action.type){
case LIST_ITEMS:
return {
...state,
lists: action.payload
};
default: return state;
}}

src\reducers\index.js

import { combineReducers } from "redux";
import crudReducer from "./crudReducer";
export default combineReducers({
lists: crudReducer
});

src\store.js

import { createStore } from "redux";
import reducer from "./reducers";
const store = createStore(reducer);
export default store;

Setting up the View with fetched data-

The first thing we’ll do is make a table to display. now create a Home(src\components\home\Home.js , \home\home.scss) and Header component.

import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import {getItems} from "../../actions/crudActions";
import './home.scss';
export default function Home() {
const dispatch = useDispatch();
const { lists } = useSelector(state => state.lists);
useEffect(() => {
dispatch(getItems());
},[dispatch]);
return (
<div> {lists && lists.map(list=>
<div key={list.id}>{list.title}</div> )}
</div>
)
}

src\components\header\Header.js and \header\header.scss

import React from "react";
import './header.scss'
export default function Header() {
return (
<div className="menu-header">
<div className="menu-header__menu-inner">
<div>
<div>REACT CRUD</div>
</div>
<button>Add</button>
</div>
</div>
)}

Now createApp.jsinside src\components\App\App.js and replace with

import React from "react";
import { Provider } from "react-redux";
//import "../../App.scss";
import store from "../../store";
import Home from "../home/Home";
export default function App() {
return (
<Provider store={store}>
<Home />
</Provider>
);
}

Now update in src\index.js from<h2>Hello</h2> to<App />

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

Yay! you must see basic list rendering.

Create a component src\components\listItem\ListItem.js and \listItem\listItem.scss

import React from "react";
import { Table } from "react-bootstrap";
import { FaEdit, FaBook } from "react-icons/fa";
import './listItem.scss';
export default function ListItem({ lists }) {
return (
<Table responsive>
<thead>
<tr>
<th><FaBook /></th>
<th>Title</th>
<th>Description</th>
<th><span>Action</span>
<span><input type="checkbox"/></span>
</th>
</tr>
</thead>
<tbody>
{lists && lists.map((list) => (
<tr key={list.id}>
<td><FaBook /></td>
<td>{list.title}</td>
<td>{list.description}</td>
<td> <FaEdit />
<input key={list.id} type="checkbox" />
</td>
</tr>
))}
</tbody>
</Table>
)}

Update your Home.js

Now we have the initial view… Yay!

Add, Update using modal & Multiple checkboxes

Now let’s update existing and create new files to make it work

create components- src\components\create\Create.js, src\components\update\Update.js, src\components\loader\Loader.js and replace from appropriate components-

replace all your components(Create.js, Header.js, Home.js, ListItem.js, Loader.js, Update.js), actions, utils, and reducers from —

src\actions\crudActions.js

src/utils/constant.js

src\reducers\crudReducer.js

multiple checkboxes — you can select multiple items to delete.

Unit Testing

Setup with Create React App

If you are new to React, we recommend using the Create React App. It is ready to use and ships with Jest! You will only need to add react-test-renderer for rendering snapshots.

npm i react-test-renderer

Snapshot Testing

Snapshot tests are a very useful tool whenever you want to make sure your UI does not change unexpectedly.

A typical snapshot test case renders a UI component, takes a snapshot, then compares it to a reference snapshot file stored alongside the test. The test will fail if the two snapshots do not match: either the change is unexpected, or the reference snapshot needs to be updated to the new version of the UI component.

Example (Create.js component)—

create a test file src\components\create\test\Create.test.js

import React from 'react';
import renderer from 'react-test-renderer';
import Create from '../Create';
test('should render Create Component', () => {
let fakeProps = {
id: 1,
title: "abc",
description: "Dummy text",
completed: false
};
const tree = renderer
.create(<Create state={fakeProps} />)
.toJSON();
expect(tree).toMatchSnapshot();
});

run test cases

npm test

Test file can be named Create.test.js or Create.spec.js

Styling with Sass

Sass is a stylesheet language that’s compiled to CSS. It allows you to use variables, nested rules, mixins, functions, and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized and makes it easy to share design within and across projects.

Sass can be installed by running this command in your terminal if not installed. Don’t need to run it again.

npm install node-sass

now create a Sass file the same way as you create CSS files, but Sass files have the file extension .scss src\components\home\home.scss

$white: #fff;@mixin phone($size) {
@media only screen and
(max-width: $size) {
@content;
}
}
.container{
padding: 30px 0px;
width: 70%;
margin: 0 auto;
.jumbotron {
padding: 0px 0px;
border-radius: 0px;
background-color: $white;
}
@include phone(480px) {
width: 100%;
margin: 0;
padding: 0;
.remove{
display: none;
}
}
}

Now create sass files inside every component folder(create/create.scss, header/header.scss, listItem/listItem.scss, loader/loader.scss, update/update.scss) and replace from styled-hooks-redux-crud/src/components/ styles files snippet.

Yay!, completed the application, Here is the demo of responsive (Desktop and mobile versions).

--

--

Vahid Akhtar
Vahid Akhtar

No responses yet