Edit and Update records in React JS using Spring Boot and MYSQL

Edit/Update Record in MYSQL using React JS and Spring Boot Application. In this article, we will learn How to Edit/Update records in MYSQL using React JS and Spring Boot Application.

Edit/Update records in React JS and Spring Boot

We will develop a simple reactJS and Spring boot application. where we will edit and update data on the server using React JS at the frontend, spring boot at the backend, and using Spring Data JPA at the Data Access Layer.

Let us divide the development process into two parts:

  • Frontend: React JS
  • Backend: Spring Boot 

Note:

Tools and Technologies Used in Spring boot and ReactJs app

  • React JS
  • Spring Boot
  • MYSQL Database
  • Spring Data JPA

Create Backend Part using Spring boot, Spring Data JPA and MYSQL

Create a Database

The first step is to create a database name ‘db_demo’ using the MYSQL command line or Workbench.

Create database db_demo

Create Project

Create a project using Spring Initializr. If you don’t know how to create a project using the same check this article https://codedec.com/tutorials/how-to-create-spring-boot-project-using-spring-initializr/

Import a Project

Now, it’s time to import the project into STS. Go to File > Import > Maven > Existing Maven Project > Next > Browse > Select the project > Finish. Now, it will take time to import the project, and similarly, all the dependencies would be added.

Configure application. properties file

# change the port
server.port=8888
#Database Configrations
spring.datasource.url=jdbc:mysql://localhost:3306/db_demo
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.database-platform = org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto = update

Create a Model Class

Now, we will create a Model class called Book.java. I have used the Lombok library to remove boilerplate code. In case you want to know what is Lombok check this article Lombok Tutorial.

Book.java

package com.abc.in.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "book")
public class Book {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private long id;
 
 private String bookName;
 
 private String authorName;
 
 private long price;
}

Create Repository Interface

Now, we will create a Data Access Layer called BookRepository which will extend JPARepository.

package com.abc.in.repository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.abc.in.model.Book;
public interface BookRepository extends JpaRepository<Book, Long>{
 
}

Create a Controller

The client request is sent to the controller which acts as an API layer that will have the endpoints for REST API.

package com.abc.in.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.abc.in.model.Book;
import com.abc.in.repository.BookRepository;

@CrossOrigin(origins = "http://localhost:3000/")
@RestController
public class BookController {

 @Autowired
 private BookRepository bookRepository;

 @GetMapping("/books")
 public Page<Book> getAllBooks(Pageable pageable) {
  return bookRepository.findAll(pageable);
 }
 
 // Get Books By Id
 @GetMapping("/book/books/{id}")
 public ResponseEntity<Book> getBookById(@PathVariable("id") long id) {
  System.out.println("here");
  return new ResponseEntity<Book>(bookRepository.findById(id).get(),HttpStatus.OK);
  
 }
 @PutMapping("/book/books/{id}")
 public ResponseEntity<Book> updateBook(@PathVariable("id") long id, @RequestBody Book book){
   Book b = bookRepository.findById(id).get();
      if(b.getId()!=0) {
        b.setBookName(book.getBookName());
        b.setAuthorName(book.getAuthorName());
        b.setPrice(book.getPrice());
      }
  return new ResponseEntity<Book>(bookRepository.save(b),HttpStatus.OK);
 }
}
  • Mark the BookController with @RestController.
  • Add, the getBookId() method to fetch a record with a particular id and also add the updateBook() method that would be called on update request.

Now, Go to the main class and run the application

package com.abc.in;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.abc.in.model.Book;
import com.abc.in.repository.BookRepository;
@SpringBootApplication
public class SpringBootBackendPartApplication{
 public static void main(String[] args) {
  SpringApplication.run(SpringBootBackendPartApplication.class, args);
 }
}

Create Frontend Part using ReactJS

Now, we will create a frontend part of the application using React JS. Open Cmd prompt > Go to the folder where you want to create a project with the help of command prompt codes > enter the command npx create-react-app book-frontend.

  • Now, open Visual Studio Code IDE and open the book-frontend app.
  • Here, you will see all the required folders and files.

We will be using bootstrap in React JS. So, open the terminal of VS code and type the following command

D:\Job Stuff\My_Study\React JS\book-frontend>npm install bootstrap

You have to install React Bootstrap also by using the following command

D:\Job Stuff\My_Study\React JS\book-frontend> npm install react-bootstrap

Install Axios library that is going to make a request to the endpoints which we have created at the backend.

D:\Job Stuff\My_Study\React JS\book-frontend> npm install axios

Now, add the Components into App.js

import logo from './logo.svg';
import './App.css';
import BookComponent from './components/BookComponent';
import MenuBar from './components/MenuBar';
import AddBooks from './components/AddBooks';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import UpdateBook from './components/UpdateBook';
import BookDeleteComponent from './components/BookDeleteComponent';
import AddBookComponent from './components/AddBookComponent';

function App() {
  return (
    <BrowserRouter>
    <div>
      <MenuBar/>
      <Switch>
        <Route exact path='/'><BookComponent/></Route>
        <Route exact path='/add-books'><AddBookComponent/></Route>
        <Route exact path='/update-books/:id'><UpdateBook/></Route>
      </Switch>
    </div>
    </BrowserRouter>
  );
}

export default App;

Create BookComponent.js

Inside the src folder, create a components folder and add a BookComponent.js and add the following lines of code.

import axios from 'axios';
import React from 'react'
import { Button, Row } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import bookService from '../services/BookService'



class BookComponent extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
            books: [],
            currentPage: 1,
            recordPerPage: 7,
            search: '',
            
        }
    }

    componentDidMount() {
        this.getBooksByPagination(this.state.currentPage);
    }
    getBooksByPagination(currentPage) {
        currentPage = currentPage - 1;
        axios.get("http://localhost:8889/books?page=" + currentPage + "&size=" + this.state.recordPerPage)
            .then(response => response.data).then((data) => {
                this.setState({
                    books: data.content,
                    totalPages: data.totalPages,
                    totalElements: data.totalElements,
                    currentPage: data.number + 1
                });
            });
    }

    //Writing All the pagination functions
    //Show Next page
    showNextPage = () => {
        if (this.state.currentPage < Math.ceil(this.state.totalElements / this.state.recordPerPage)) {
            if (!this.state.search) {
                this.getBooksByPagination(this.state.currentPage + 1);
            } else {
                this.searchBook(this.state.currentPage + 1)
            }
        }
    };

    //Show Last Page
    showLastPage = () => {
        if (this.state.currentPage < Math.ceil(this.state.totalElements / this.state.recordPerPage)) {
            if (!this.state.search) {
                this.getBooksByPagination(Math.ceil(this.state.totalElements / this.state.recordPerPage));
            }
            else {
                this.searchBook(Math.ceil(this.state.totalElements / this.state.recordPerPage));
            }
        }
    };
    //Show First page
    showFirstPage = () => {
        let firstPage = 1;
        if (this.state.currentPage > firstPage) {
            if (!this.state.search) {
                this.getBooksByPagination(firstPage);
            } else {
                this.searchBook(firstPage)
            }
        }
    };

    //Show previous page
    showPrevPage = () => {
        let prevPage = 1
        if (this.state.currentPage > prevPage) {
            if (!this.state.search) {
                this.getBooksByPagination(this.state.currentPage - prevPage);
            } else {
                this.searchBook(this.state.currentPage - prevPage);
            }
        }
    };
    //Search Box Method
    searchBox = (e) => {
        this.setState({
            //assigning value to event target
            [e.target.name]: e.target.value,
        });
    };
    //Search Method Logic
    searchBook = (currentPage) => {
        currentPage = currentPage - 1;
        axios.get("http://localhost:8889/books/" + this.state.search + "?page=" + currentPage + "&size=" + this.state.recordPerPage)
            .then(response => response.data).then((data) => {
                this.setState({
                    books: data.content,
                    totalPages: data.totalPages,
                    totalElements: data.totalElements,
                    currentPage: data.number + 1
                });
            });
    };

    //Reset Search Box
    resetBook = (currentPage) => {
        this.setState({ "search": '' });
        this.getBooksByPagination(this.state.currentPage);
    };
    //Delete Book on the web page
    deleteBook = (id) => {
        axios.delete("http://localhost:8889/books/" + id).then(
            (response) => {
                alert("Record Deleted Successfully");
                this.setState({
                    books: this.state.books.filter(book => book.id !== id)
                });
            }, (error) => {
                alert("Operation Failed Here");
            }
        );
    };
    render() {
        const { books, currentPage, totalPages, recordPerPage, search } = this.state;
        return (
            <div>

                <h1 className="text-center mt-5 ">List of Books</h1>
                <div className="container mt-2">
                    <div style={{ float: 'center' }} align="center">
                        <div class="form-group mb-2">
                            <input type="text" class="form-control" name="search" size="50" placeholder="Search Here" value={search} onChange={this.searchBox} />
                            <button type="button" name="search" class="btn btn-info my-2 text-center mr-2" onClick={this.searchBook}>Search Book</button>
                            <button type="reset" class="btn btn-secondary text-center ml-5" style={{ marginLeft: '10px' }} onClick={this.resetBook}>Clear Book</button>
                        </div>
                    </div>
                    <table className="table table-bordered border-info shadow">
                        <thead>
                            <tr>
                                <th>#</th>
                                <th>Book Name</th>
                                <th>Book Author</th>
                                <th>Price</th>
                                <th>Action</th>
                            </tr>
                        </thead>
                        <tbody>
                            {books.length === 0 ?
                                <tr align="center"><td colSpan="5">No Record Found</td></tr> :
                                books.map(
                                    (books, index) => (
                                        <tr key={books.id}>
                                            <td>{(recordPerPage * (currentPage - 1)) + index + 1}</td>
                                            <td>{books.bookName}</td>
                                            <td>{books.authorName}</td>
                                            <td>{books.price}</td>
                                            <td><button className="btn btn-outline-danger" onClick={() => { this.deleteBook(books.id) }}>Delete</button>
                                            <Link to={`/update-books/${books.id}`} className="btn btn-outline-dark">Edit</Link>
                                            </td>

                                        </tr>
                                    )
                                )
                            }
                        </tbody>

                    </table>
                    <table className="table">
                        <div style={{ float: 'left', fontFamily: 'monospace', color: '#0275d8' }}>
                            Page {currentPage} of {totalPages}
                        </div>
                        <div style={{ float: 'right' }}>
                            <div class="clearfix"></div>
                            <nav aria-label="Page navigation example">
                                <ul class="pagination">
                                    <li class="page-item"><a type="button" class="page-link" disabled={currentPage === 1 ? true : false} onClick={this.showPrevPage}>Previous</a></li>
                                    <li class="page-item"><a type="button" class="page-link" disabled={currentPage === 1 ? true : false} onClick={this.showFirstPage}>First</a></li>
                                    <li class="page-item"><a type="button" class="page-link" disabled={currentPage === totalPages ? true : false} onClick={this.showNextPage}>Next</a></li>
                                    <li class="page-item"><a type="button" class="page-link" disabled={currentPage === totalPages ? true : false} onClick={this.showLastPage}>Last</a></li>
                                </ul>
                            </nav>
                        </div>
                    </table>
                </div>
            </div>
        )
    }
}
export default BookComponent

In this file, just add the link for update-books as shown below.  (Here, in this code, we have also added the Pagination, Searching Functionality If you want to know How it is done check this article https://codebun.com/search-record-from-a-table-in-react-js-spring-boot-and-mysql/)

<Link to={`/update-books/${books.id}`} className="btn btn-outline-dark">Edit</Link>

Create UpdateBook.js

Inside the src folder, create a components folder and add UpdateBook.js and add the following lines of code.

import React,{useState,useEffect} from 'react'
import axios from 'axios';
import {useParams} from "react-router-dom";

function UpdateBook() {

    const {id} = useParams(); // getting url id        
    const URL = `http://localhost:8889/book/books/${id}`;
   

    useEffect(()=>{
        getBookById();
    },[])
    const [book, setBook] = useState({
        bookName:"",
        authorName:"",
        price:"",        
    });

    const { bookName , authorName , price} = book;
    const onInputChange = e =>{
        setBook({...book,[e.target.name]:e.target.value})
    }
    

    const FormHandle = e =>{
        e.preventDefault();
        updateDataToServer(book)      
    }
    const updateDataToServer=(data) =>{
        axios.put(URL,data).then(
           (response)=>{
                   alert("Book Updated Successfully");
            },(error)=>{
                    alert("Operation failed");
            }
        );
    };
    
    const getBookById= async e =>{
        const booksInfo = await axios.get(URL);
        setBook(booksInfo.data);       
    }
   
    return (
        <div>
            <div className="container">
            <div className="w-75 mx-auto shadow p-5 mt-2 bg-light">
                <div class="jumbotron">
                    <h1 class="display-4 text-center">Update Books!</h1>
                    <div>
                    <form onSubmit={e => FormHandle(e)}>
                        <div class="form-group">
                            <label for="exampleInputEmail1">Book Name</label>
                            <input type="text" class="form-control" name="bookName"   placeholder="Enter Here" value={bookName} onChange={(e) =>onInputChange(e)} />
                        </div>
                        <div class="form-group">
                            <label for="exampleInputPassword1">Book Author</label>
                            <input type="text" class="form-control" name="authorName"   placeholder="Enter Here" value={authorName} onChange={(e) =>onInputChange(e)} />
                        </div>
                        <div class="form-group">
                            <label for="exampleInputPassword1">Book Price</label>
                            <input type="text" class="form-control" name="price"  placeholder="Enter Here" value={price} onChange={(e) =>onInputChange(e)}  />
                        </div>
                        <div className="container text-center">
                        <button type="submit" class="btn btn-outline-success my-2 text-center mr-2">Update Book</button>
                        <button type="reset" class="btn btn-outline-primary text-center mr-2">Clear Book</button>
                        </div>
                    </form>
                </div>
            </div>
            </div>
        </div>
        </div>
    )
}
export default UpdateBook

Now, let us divide the code and understand the working of it. (Here, the code is similar to the insert book check this article https://codebun.com/how-to-insert-data-into-mysql-using-react-js-and-spring-boot/) with some minute changes as discussed below.

  • Get the id from the URL using useParams
const {id} = useParams();
  • Pass the id to the endpoints
const URL = `http://localhost:8889/book/books/${id}`;
  • Call the getBookById in useEffect as shown below. After that, get particular book information by making a request to the backend and set the data to the state.
useEffect(()=>{
       getBookById();
},[])
const getBookById= async e =>{
        const booksInfo = await axios.get(URL);
        setBook(booksInfo.data);       
    }
  • Now, call the FormHandle() method to submit a form. Inside it Define the updateDataToServer(book) method and use the Axios library to make an HTTP PUT request to the backend.
const FormHandle = e =>{
        e.preventDefault();
        updateDataToServer(book)
        console.log(book)       
}
const updateDataToServer=(data) =>{
        axios.put(URL,data).then(
           (response)=>{
                   console.log(response);
                   alert("Book Updated Successfully");
            },(error)=>{
                    console.log(error);
                    alert("Operation failed");
            }
        );
    };

Run the React JS app by going to the terminal and enter the following command

D:\Job Stuff\My_Study\React JS\book-frontend> npm start

At localhost:3000 you will be able to see the following output.

In this way, we learn how to Edit/Update records in MYSQL using React JS and Spring Boot Application.

If you want to learn how to display a list on the page using React JS and Spring Boot application check this article How to Create Spring Boot and ReactJs application with MYSQL.

ReactJs and Spring boot Practice Tasks

https://codebun.com/how-to-insert-data-into-mysql-using-react-js-and-spring-boot/

https://codebun.com/delete-record-from-a-table-in-react-js-spring-boot-and-mysql/

https://codebun.com/search-record-from-a-table-in-react-js-spring-boot-and-mysql/

https://codebun.com/how-to-create-a-pagination-in-react-js-and-spring-boot/

https://codebun.com/how-to-create-spring-boot-and-reactjs-application/