Views

Frontend using ReactJS and TypeScript

Frontend using ReactJS and TypeScript
Page content

In this article, I will be developing a Model-View-Controller (MVC) application using ReactJS Framework, which would consume the REST APIs created in Microservices.

If you want to understand more about MVC Architecture, go through this article.

By the end of this article, you would learn about how to:

  • Develop a Frontend MVC Application using ReactJS Framework.
  • How to call and consume REST APIs of microservice, from application developed using ReactJS Framework.

If you have no time to read this article completely, but want to try the code for yourself, GitHub location is provided here.


Prerequisites

There are some prerequisites that are required for creating the Frontend Application.

Familiarity with Technologies and Frameworks

It is assumed that you have prior knowledge or familiarity with JavaScript, TypeScript and HTML. Because, I will not be covering the basics of these in this article.

If you are not familiar, then it is advised to get the basic knowledge of these and then come back to this site.

Node.js v8+

Download the latest version of the Node.js from here. Click the downloaded .msi and complete the installation.

Embedded npm available in the Node.js package.

webpack for building Frontend.

IDE for code development

You can use any IDE of your choice, that supports TypeScript. I will be using the Visual Studio Code.

If you wish to use the Visual Studio Code, download the latest version from here. Click on the downloaded .exe and complete the installation.


Create a Base ReactJS Project

To create new Base (plain project, without any customization) ReactJS Project, open the command prompt and type the command:

npx create-react-app frontend-react

Where frontend-react is the name of my project. On successful creation of react project – frontend-react, you will see the message similar to below.

react-project-create-success.jpeg
Successful creation of ReactJS Project

Running the ReactJS Project

To run the ReactJS Application, first get into the project folder and start the npm server. Type the following command shown below: 

1cd frontend-react
2npm start

react-start-server.jpeg
ReactJS Server started

Application will be launched in the default browser at http://localhost:3000/ and Vanilla ReactJS Project Welcome Page will be displayed.

react-default-app-screen.jpeg
ReactJS Vanilla Welcome Page


Adding Bootstrap Module to ReactJS Project

Bootstrap Module helps with some pre built CSS and JavaScript for styling and is used widely. In order to add the Bootstrap Module to our ReactJS project, follow the steps given below:

  • From inside the Project folder, type in the command:
npm install bootstrap --save bootstrap
  • Open index.js and add following line at the very top of the file:
import 'bootstrap/dist/css/bootstrap.css';

Importing ReactJS Project into Visual Studio Code

There are two ways of importing projects into Visual Studio Code Application:

  1. Through Visual Studio Code Application itself
    • Open the Visual Studio Code Application.
    • Select File → Open Folder → <Browse to the project location> and click **Select Folder**.
  2. Through Command Prompt
    • Go to the project folder, open the command prompt and type the below command and entire project will be imported into Visual Studio Code Application:
code .

Final project structure would look something like below:

react-final-project-structure.jpeg
ReactJS Final Project Structure

Congratulations, you have successfully configured and run your first default React project


Enhancing the Vanilla Application to consume REST APIs

Let us start building the frontend components for our Todo Tracker Application, so that we can consume the REST APIs exposed by our microservice application, mentioned below:

Description CRUD Operation HTTP Method REST API Endpoint
Create New Todo Task CREATE POST /tasks
Fetch All Todo Tasks READ GET /tasks
Fetch One Todo Task READ GET /tasks/{id}
Update One Specific Todo Task UPDATE PUT /tasks
Delete One Specific Todo Task DELETE DELETE /tasks/{id}

Display All items

Description CRUD Operation HTTP Method REST API Endpoint
Fetch All Todo Tasks READ GET /tasks

For consuming this endpoint, we will need to add following components:

  • Create new Component = /src/todo-application/component/TodoApplicationComponent.jsx
 1import React, { Component } from 'react';
 2import TodoApplicationView from '../view/TodoApplicationView';
 3
 4class TodoApplicationComponent extends Component {    
 5   render() {        
 6      return (              
 7         TodoApplicationView (this)        
 8      )    
 9   }
10} 
11export default TodoApplicationComponent
  • Update the App.js to display TodoApplication component
 1import React from 'react';
 2import './App.css';
 3import TodoApplication from './todo-application/component/TodoApplication';
 4
 5function App() {
 6  return (
 7    <div className="container">
 8        <h1 align="center">Todo Tracker Application</h1>
 9        <TodoApplication />
10    </div>
11  );
12}
13
14export default App;

Hardcode the values

  • Create View Component to display complete list of the Todo Tracker List = /src/todo-application/view/TodoApplicationView.jsx
 1import React from 'react';
 2
 3const TodoApplicationView = (component) => {
 4    return (
 5        <div className="container">  
 6            <table className='table-striped' border='1' align="center">
 7                <thead>
 8                    <tr>
 9                        <th>Title</th>
10                        <th>Description</th>
11                        <th>Due Date</th>
12                        <th>Status</th>
13                        <th>No of Comments</th>
14                    </tr>
15                </thead>
16                <tbody>
17                    <tr>
18                        <td>Test the Application</td>
19                        <td>Test the Application - Hard code</td>
20                        <td>31-Oct-2021</td>
21                        <td>IN_PROGRESS</td>
22                        <td align='center'>0</td>
23                    </tr>
24                </tbody>
25            </table>
26        </div>             
27    );
28}
29
30export default TodoApplicationView

The output on the browser, when we type: http://localhost:3000/

react-hardcoded-output.jpeg
ReactJS Application with Hardcoded Values

At this stage, we are able to display the list of components, that are hardcoded onto our ReactJS component.


Connect REST API with the ReactJS Project

Before we continue with connecting our ReactJS Project to REST API, we need to add module required to make the REST API calls – axios

  • Add axios module to the project by opening the command prompt, in the project folder and type:
npm add axios
  • Create Service Component - to make the REST API calls = /src/todo-application/service/TodoService.jsx
1import axios from 'axios'
2
3const TODO_API_URL = 'http://localhost:8080/todo-app/tasks'
4class TodoService {
5    retrieveAllTodoList() {
6        return axios.get(`${TODO_API_URL}`);
7    }
8}
9export default new TodoService()
  • Update the Component to make sure TodoService.jsx API call is invoked = /src/todo-application/component/TodoApplicationComponent.jsx
 1import  { Component } from 'react';
 2
 3import TodoService from '../service/TodoService';
 4import TodoApplicationView from '../view/TodoApplicationView';
 5
 6class TodoApplicationComponent extends Component {
 7    componentDidMount() {
 8        this.retrieveAllTodoList();
 9    }
10
11    retrieveAllTodoList() {
12        TodoService.retrieveAllTodoList()
13        .then(
14            response => {
15                console.log(response);
16            }
17        )
18    }
19
20    render() {        
21        return (
22            TodoApplicationView (this)
23        )        
24    }
25}
26export default TodoApplicationComponent

When we refresh the Browser, we get the below CORS Request Error.

Access to XMLHttpRequest at 'http://localhost:8080/todo-app/tasks' from origin 'http://localhost:3000' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The microservice application’s REST API is running on http://localhost:8080/, and it is not allowing requests from other servers/domains - http://localhost:3000/ (in our case here).

This is called CORS (Cross-Origin Resource Sharing) policy, where in by default, servers block request coming from other servers or domains.

Click here to know more about how to enable CORS Policy and resolve this error.

After enabling CORS on Microservice Application, if we refresh the browser - http://localhost:3000/, we should see the output from REST APIs microservice application, printed on the browser console (Click Developer Tools from settings or F12 on most browsers).

rest-api-output-directed-to-console.jpeg
REST API Output on Console


Display REST API results on ReactJS Component

Let us move ahead and display the REST API output onto the React component, hence on the React App browser page.

  1. Update the Component, to store the response data using the state object = /src/todo-application/component/TodoApplicationComponent.jsx
 1class TodoApplicationComponent extends Component {
 2
 3    constructor(props) {
 4        super(props);
 5        this.state = {
 6            todoList: []
 7        }
 8    }
 9   
10   retrieveAllTodoList() {
11        TodoService.retrieveAllTodoList()
12        .then(
13            response => {
14                this.setState({ todoList: response.data })
15            }
16        )
17    }
18
19    render() {
20        return (
21            TodoApplicationView (this)
22        )
23    }
24}
25export default TodoApplicationComponent
  1. Update View Component to render/display the stored data from the component= /src/todo-application/view/TodoApplicationView.jsx
 1import React from 'react';
 2import Moment from 'moment';
 3
 4const TodoApplicationView = (component) => {
 5    return (
 6        <div className="container">  
 7            <table className='table-striped' border='1' align="center">
 8                <thead>
 9                    <tr>
10                        <th>Title</th>
11                        <th>Description</th>
12                        <th>Due Date</th>
13                        <th>Status</th>
14                        <th>No of Comments</th>
15                    </tr>
16                </thead>
17                <tbody>
18                    { component.state.todoList.map(todoItem =>
19                        <tr key={todoItem.id}>
20                            <td>{todoItem.title}</td>
21                            <td>{todoItem.description}</td>
22                            <td>{ Moment(todoItem.dueDate).format('DD-MMM-YYYY') }</td>
23                            <td>{todoItem.status}</td>
24                            <td align='center'>{todoItem.todoTaskCommentsSet.length}</td>
25                        </tr>
26                    )}                    
27                </tbody>
28            </table>
29        </div>             
30    );
31}
32
33export default TodoApplicationView

Refresh the React App browser page and we will see the response coming from microservice REST API.

rest-api-output-on-frontend.jpeg
REST API Output on ReactJS App


Display One Item

To display only one item, we need to update the following components.

  1. Update the View Component to add a VIEW Button for displaying single item = /src/todo-application/view/TodoApplicationView.jsx
 1const TodoApplicationView = (component) => {
 2    return (
 3        <div className="container">  
 4            <table className='table-striped' border='1' align="center">
 5                <thead>
 6                    <tr>
 7                        <th>Title</th>
 8                        <th>Description</th>
 9                        <th>Due Date</th>
10                        <th>Status</th>
11                        <th>No of Comments</th>
12                        <th>View</th>
13                    </tr>
14                </thead>
15                <tbody>
16                    { component.state.todoList.map(todoItem =>
17                        <tr key={todoItem.id}>
18                            <td>{todoItem.title}</td>
19                            <td>{todoItem.description}</td>
20                            <td>{ Moment(todoItem.dueDate).format('DD-MMM-YYYY') }</td>
21                            <td>{todoItem.status}</td>
22                            <td align='center'>{todoItem.todoTaskCommentsSet.length}</td>
23                            <td><button className="btn btn-success" onClick={() => component.view(todoItem)}>View</button></td>
24                        </tr>
25                    )}
26                    
27                </tbody>
28            </table>
29        </div>             
30    );
31}
32
33export default TodoApplicationView
  1. Create a View Component for displaying Single View Item = /src/todo-application/view/TodoApplicationSingleItemView.jsx
 1import React from 'react';
 2import Moment from 'moment';
 3
 4const TodoApplicationSingleItemView = (component) => {
 5    const todoItem = component.state.todoItem;
 6    
 7    return (            
 8        <form className="container">
 9            <table className='table-striped' border='1'> 
10                <tbody>                 
11                    <tr>
12                        <th>Title</th>
13                        <td> { todoItem.title } </td>                                
14                        </tr><tr>
15                        <th>Description</th>
16                        <td> { todoItem.description } </td>
17                    </tr>
18                    <tr>
19                        <th>Creation Date</th>
20                        <td> { Moment(todoItem.creationDate).format('DD-MMM-YYYY') } </td>
21                    </tr>
22                    <tr>
23                        <th>Due Date</th>
24                        <td> { Moment(todoItem.dueDate).format('DD-MMM-YYYY') } </td>
25                    </tr><tr>
26                        <th>Status</th>
27                        <td> { todoItem.status } </td>
28                    </tr>
29                    <tr>                    
30                        <th>Comments</th>
31                        <td>
32                        
33                            <table className='table-striped' border='1'>
34                                <thead>
35                                { todoItem.todoTaskCommentsSet.length > 0 &&
36                                    <tr>
37                                        <th>Date</th>
38                                        <th>Comments</th>
39                                    </tr>
40                                }
41                                </thead>
42                                <tbody>
43                                { todoItem.todoTaskCommentsSet.map(todoComments => 
44                                    <tr key={todoComments.todoTaskCommentsId}>
45                                        <td>{ Moment(todoComments.creationDate).format('DD-MMM-YYYY') }</td>
46                                        <td>{todoComments.taskComments}</td>
47                                    </tr>
48                                )}
49                                </tbody>
50                            </table>
51                        
52                        </td>
53                    </tr>
54                </tbody>  
55            </table> 
56        </form>
57    );    
58}
59
60export default TodoApplicationSingleItemView
  1. Update the Component to display the single view = /src/todo-application/component/TodoApplicationComponent.jsx
 1import TodoApplicationView from '../view/TodoApplicationView';
 2import TodoApplicationSingleItemView from '../view/TodoApplicationSingleItemView';
 3
 4class TodoApplicationComponent extends Component {
 5    constructor(props) {
 6        super(props);
 7        this.state = {
 8            todoList: [],
 9            todoItem: {
10                systemTasksId: '',
11                title: '',
12                description:'',
13                creationDate:'',
14                dueDate:'',
15                status:'',
16                todoCommentsSet:[]
17            }
18        }
19    }
20
21    view(todoItem) {
22        this.setState( { todoItem : todoItem });
23    }
24
25    render() {
26        if(this.state.todoItem.systemTasksId === '') {
27            return (
28                TodoApplicationView (this)
29            )
30        } else {
31            return (
32                TodoApplicationSingleItemView (this)
33            )
34        }
35    }
36}
37export default TodoApplicationComponent

There are quite a few changes to this Component file. Lets go one by one:

  • Import the newly created View Component for displaying Single View Item.
import TodoApplicationSingleItemView from '../view/TodoApplicationSingleItemView';
  • Creating and initializing the stateful object for todoItem.
todoItem: {
    systemTasksId: '',
    title: '',
    description:'',
    creationDate:'',
    dueDate:'',
    status:'',
    todoCommentsSet:[]
}
  • Creating a method called View for the View button created in /view/TodoApplicationView.jsx
view(todoItem) {
    this.setState( { todoItem : todoItem });
}
  • Updating the render method to include the call to the newly created /view/TodoApplicationSingleItemView.jsx
render() {
    if(this.state.todoItem.systemTasksId === '') {
        return (
            TodoApplicationView (this)
        )
    } else {
        return (
            TodoApplicationSingleItemView (this)
        )
    }
}

Refresh the React App browser page and we will see response similar to this:

react-view-button.jpeg
ReactJS App with View Button

When we click on View button, we get the below page

react-single-item-view.jpeg
ReactJS App - Single Item View Page


Update One Item

Description CRUD Operation HTTP Method REST API Endpoint
Update One Specific Todo Task UPDATE PUT /tasks
  1. Update the Service Component= /src/todo-application/service/TodoService.jsx
update(todoItem) {
    return axios.put(`${TODO_API_URL}`, todoItem)
}
  1. Update the Component to include the function for Edit button, redirection to Single View Component page for Editing, functions for handling Submit and event change= /src/todo-application/component/TodoApplicationComponent.jsx
 1class TodoApplicationComponent extends Component {
 2    constructor(props) {
 3        super(props);
 4        this.state = {
 5            todoList: [],
 6            todoItem: {...},
 7            todoTaskComments: {
 8                taskComments: ''
 9            },
10            statusList:[],
11            action: '',
12            showCommentTable: false
13        }
14
15        this.handleChange = this.handleChange.bind(this)
16        this.handleSubmit = this.handleSubmit.bind(this)
17    }
18
19    toggleComments(){
20        this.setState({
21            showCommentTable: !this.state.showCommentTable
22        })
23    }
24
25    componentDidMount() {
26        this.retrieveAllTodoList();
27        this.getStatus();
28    }
29
30    getStatus() {
31        TodoService.retrieveTodoStatus()
32        .then(response => {
33            let statusFromApi = response.data.map(status => {
34                return {value: status, display: status}
35              });
36              this.setState({ 
37                statusList: [{value: '', display: '--Select Status--'}].concat(statusFromApi)
38               })
39        })
40    }
41    
42    view(todoItem) {
43        console.log('view= ' + JSON.stringify(todoItem))
44        this.action='view';
45        this.setState( { todoItem : todoItem });
46    }
47
48    edit(todoItem) {
49        console.log('edit= ' + JSON.stringify(todoItem))
50        this.action='edit';
51        this.setState( { todoItem : todoItem, todoTaskComments: {taskComments:''} });
52    }
53
54    handleChange = (e) => {
55        const name = e.target.name;
56        const value = e.target.value;
57
58        this.setState( prevState => ({ todoItem : 
59            {...prevState.todoItem, [name]: value }
60        })) 
61        this.setState( prevState => ({ todoTaskComments : 
62            {...prevState.todoTaskComments, [name]: value }
63        })) 
64      }
65
66    handleSubmit(todoItem, todoTaskComments) {
67        console.log('submit= ' + JSON.stringify(todoItem) +' && '+JSON.stringify(todoTaskComments));
68        
69        var todoTaskCommentsArray= [];
70        todoTaskCommentsArray.push(todoTaskComments);
71        todoItem.todoTaskCommentsSet=todoTaskCommentsArray;
72        TodoService.create(todoItem);   
73        this.retrieveAllTodoList();   
74    }
75}
76export default TodoApplicationComponent
  1. Update the View Component to include the Edit button = /src/todo-application/view/TodoApplicationView.jsx
 1const TodoApplicationView = (component) => {
 2    return (
 3        <div className="container">  
 4            <table className='table-striped' border='1' align="center">
 5                <thead>
 6                    <tr>
 7                        <th>Title</th>
 8                        <th>Description</th>
 9                        <th>Due Date</th>
10                        <th>Status</th>
11                        <th>No of Comments</th>
12                        <th>View</th>
13                        <th>Edit</th>
14                    </tr>
15                </thead>
16                <tbody>
17                    { component.state.todoList.map(todoItem =>
18                        <tr key={todoItem.id}>
19                            <td>{todoItem.title}</td>
20                            <td>{todoItem.description}</td>
21                            <td>{ Moment(todoItem.dueDate).format('DD-MMM-YYYY') }</td>
22                            <td>{todoItem.status}</td>
23                            <td align='center'>{todoItem.todoTaskCommentsSet.length}</td>
24                            <td><button className="btn btn-success" onClick={() => component.view(todoItem)}>View</button></td>
25                            <td><button className="btn btn-success" onClick={() => component.edit(todoItem)}>Edit</button></td>
26                        </tr>
27                    )}
28                    
29                </tbody>
30            </table>
31        </div>             
32    );
33}
34
35export default TodoApplicationView
  1. Update the Single View Component to include the functionality for Editing = /src/todo-application/view/TodoApplicationSingleItemView.jsx
  1const TodoApplicationSingleItemView = (component) => {
  2    const action = component.action;
  3    const todoItem = component.state.todoItem;
  4    const todoTaskComments = component.state.todoTaskComments;
  5    const statusList = component.state.statusList;
  6    const handleChange = component.handleChange;
  7    const handleSubmit = component.handleSubmit;
  8    
  9    return (            
 10        <form className="container">
 11            <table className='table-striped' border='1'> 
 12                <tbody>                 
 13                    <tr>
 14                        <th>Title</th>
 15                        <td> {
 16                            action === 'view' ? todoItem.title : 
 17                            <input type='text' name='title' value= {todoItem.title} onChange={handleChange} size="35"></input>
 18                        } </td>                                
 19                        </tr><tr>
 20                        <th>Description</th>
 21                        <td> {
 22                            action === 'view' ? todoItem.description : 
 23                            <textarea name='description' value= {todoItem.description} onChange={handleChange} rows="3" cols="37"></textarea>
 24                        } </td>
 25                    </tr>
 26                    {todoItem.id > 0 &&
 27                    <tr>
 28                        <th>Creation Date</th>
 29                        <td> { Moment(todoItem.creationDate).format('DD-MMM-YYYY') } </td>
 30                    </tr>
 31                    }
 32                    <tr>
 33                        <th>Due Date</th>
 34                        <td> {
 35                            action === 'view' ? Moment(todoItem.dueDate).format('DD-MMM-YYYY') :
 36                             <input type='date' name='dueDate' value= {todoItem.dueDate} onChange={handleChange}></input>
 37                        } </td>
 38                    </tr><tr>
 39                        <th>Status</th>
 40                        <td> {
 41                            action === 'view' ? todoItem.status : 
 42                            <select name='status' value={todoItem.status} onChange={handleChange}>
 43                                {statusList.map((status) => <option key={status.value} value={status.value}> {status.display}</option>)}
 44                            </select>
 45                        } </td>
 46                    </tr>
 47                    {todoItem.id > 0 &&
 48                    <tr>                    
 49                        <th>Comments</th>
 50                        <td>
 51                        
 52                            <table className='table-striped' border='1'>
 53                                <thead>
 54                                { todoItem.todoTaskCommentsSet.length > 0 &&
 55                                    <tr>
 56                                        <th>Date</th>
 57                                        <th>Comments</th>
 58                                    </tr>
 59                                }
 60                                </thead>
 61                                <tbody>
 62                                { todoItem.todoTaskCommentsSet.map(todoComments => 
 63                                    <tr key={todoComments.todoTaskCommentsId}>
 64                                        <td>{ Moment(todoComments.creationDate).format('DD-MMM-YYYY') }</td>
 65                                        <td>{todoComments.taskComments}</td>
 66                                    </tr>
 67                                )}
 68                                { action === 'edit' &&
 69                                <>
 70                                    <tr>
 71                                        <td colSpan="2">
 72                                            <button type="button" className="btn btn-success" onClick={() => component.toggleComments()}>Add New Comments</button>
 73                                        </td>
 74                                    </tr>
 75                                    {component.state.showCommentTable &&
 76                                    <tr>
 77                                    <td colSpan="2">
 78                                        <table>
 79                                            <tbody>
 80                                            <tr>
 81                                                <th>Description</th>
 82                                                <td>
 83                                                    <textarea rows="2" cols="24" name='taskComments' value= {todoTaskComments.taskComments} onChange={handleChange}></textarea>
 84                                                </td>
 85                                            </tr>
 86                                            </tbody>
 87                                        </table>
 88                                    </td>
 89                                    </tr>                                    
 90                                    }
 91                                </>
 92                                }
 93                                </tbody>
 94                            </table>
 95                        
 96                        </td>
 97                    </tr>
 98                     }
 99                    <tr>
100                        {action === 'view' ? null:
101                            <td colSpan='2' align='center'><button className="btn btn-success" onClick={() => handleSubmit(todoItem,todoTaskComments)}>Submit</button></td>
102                        }
103                    </tr>
104                </tbody>  
105            </table> 
106        </form>
107    );    
108}
109
110export default TodoApplicationSingleItemView

When the browser refreshes, if your updates are fine, you should see page similar to the following.

react-edit-button.jpeg
ReactJS App - with Edit Button

On clicking EDIT button

react-edit-mode.jpeg
ReactJS App - Single Item View Page - Edit Mode

On clicking ADD NEW COMMENTS button

react-add-new-comments-button.jpeg
On Clicking Add New Comments Button

On clicking SUBMIT button, after updates and adding new Comment

react-after-edit.jpeg
ReactJS App - After Edit


Delete one item from the list

Description CRUD Operation HTTP Method REST API Endpoint
Delete One Specific Todo Task DELETE DELETE /tasks/{id}
  1. Update the Service Component, to add the Delete REST API call=/src/todo-application/service/TodoService.jsx
1deleteById(id) {
2    return axios.delete(`${TODO_API_URL}/${id}`)
3}
  1. Update the Component, to include the function for delete=/src/todo-application/component/TodoApplicationComponent.jsx
 1class TodoApplicationComponent extends Component {
 2    delete(id) {
 3        TodoService.deleteById(id)
 4        .then(
 5            response => {
 6                this.retrieveAllTodoList();
 7            }
 8        )
 9    }
10}
  1. Update the View Component to include the Delete button=/src/todo-application/view/TodoApplicationView.jsx
 1const TodoApplicationView = (component) => {
 2    return (
 3        <div className="container">  
 4            <table className='table-striped' border='1' align="center">
 5                <thead>
 6                    <tr>
 7                        <th>Title</th>
 8                        <th>Description</th>
 9                        <th>Due Date</th>
10                        <th>Status</th>
11                        <th>No of Comments</th>
12                        <th>View</th>
13                        <th>Edit</th>
14                        <th>Delete</th>
15                    </tr>
16                </thead>
17                <tbody>
18                    { component.state.todoList.map(todoItem =>
19                        <tr key={todoItem.id}>
20                            <td>{todoItem.title}</td>
21                            <td>{todoItem.description}</td>
22                            <td>{ Moment(todoItem.dueDate).format('DD-MMM-YYYY') }</td>
23                            <td>{todoItem.status}</td>
24                            <td align='center'>{todoItem.todoTaskCommentsSet.length}</td>
25                            <td><button className="btn btn-success" onClick={() => component.view(todoItem)}> View</button></td>
26                            <td><button className="btn btn-success" onClick={() => component.edit(todoItem)}> Edit</button></td>
27                            <td><button className="btn btn-warning" onClick={() => component.delete(todoItem.id)}> Delete</button></td>
28                        </tr>
29                    )}
30                    
31                </tbody>
32            </table>
33        </div>             
34    );
35}
36
37export default TodoApplicationView

Refresh the React App browser page and we will see response similar to this:

react-delete-button.jpeg
ReactJS App - with Delete Button

After deleting the first entry

react-after-delete.jpeg
ReactJS App - After Delete


Create New Item

Description CRUD Operation HTTP Method REST API Endpoint
Create New Todo Task CREATE POST /tasks
  1. Update the Service component= /src/todo-application/service/TodoService.jsx
 1create(todoItem) {        
 2    axios({
 3        method: 'post',
 4        url: `${TODO_API_URL}`,
 5        headers: {
 6            'Content-Type': 'application/json'
 7        },
 8        data: todoItem
 9    });
10    // return axios.post(`${TODO_API_URL}`, todoItem)
11}
  1. Update the Component = /src/todo-application/component/TodoApplicationComponent.jsx
1class TodoApplicationComponent extends Component {
2    create() {
3        this.action='edit';
4         this.setState( { todoItem: 
5            { title: '', description:'', dueDate:'', status:'' } ,
6            todoTaskComments: {taskComments:''}
7        });
8    }
9}
  1. Update View Component = /src/todo-application/view/TodoApplicationView.jsx
 1const TodoApplicationView = (component) => {
 2    return (
 3        <div className="container">  
 4            <button className="btn btn-success" onClick={() => component.create ()}>Create</button>
 5            <table className='table-striped' border='1' align="center">
 6                ...
 7            </table>
 8        </div>             
 9    );
10}
11
12export default TodoApplicationView

When the browser refreshes, if your updates are fine, you should see page similar to the following.

react-create-button.jpeg
ReactJS - With CREATE Button

On clicking CREATE button

react-create-mode.jpeg
On Clicking CREATE Button

After Submission

react-after-create.jpeg
After Submitting


Conclusion

With this setup complete, we have come to the end of this article.

At the end of this article, we have learned how to:

  • Develop a Frontend MVC Application using ReactJS Framework.
  • How to call and consume REST APIs of microservice, from application developed using ReactJS Framework.

Complete code for this project can be found at GitHub here. Go ahead and clone it.

Instructions on how to clone and run the project are provided on the GitHub page.