jueves, 5 de agosto de 2021

React - Spring Boot Full Stack FrontEnd BackEnd Person Entity CRUD App

React - Spring Boot Full Stack FrontEnd BackEnd Person Entity CRUD App

Simple CRUD application






List Persons


Add Person


List Person after Add Person


List Persons after Delete Person


Update Person


List Person after Update person


Detail Person



CRUD features

- Create Person
- List Person
- Update Person
- Delete Person
- View Person

React is used to build user interfaces on the fron end.
Spring boot to develop REST web services and microservices. reduces configuration and set up time required for 
spring projects.

REST api call from React to Spring Boot RESTfull API
basic React components JSX, State and Props

Tools and Technologies


- React
- Modern JaveScript (ES6)
- NodeJs and NPM
- VS Code IDE
- Create React App CLI
- Bootstrap 4.5 and Axios HTTP Library
- Spring Boot 2+
- SprinData JPA (Hibernate)
- Maven 3.2+
- JDK 1.8
- Embedded Tomcat 8.5+
- PostgreSQL database


Create Spring Boot Project

New Spring starter Project
springboot-backend
Maven jar
8 java

Spring boot version 2.3.1
Spring Boot DevTools
Spring Data JPA
MySQL Driver
Spring Web

Create DataBase Person   (Postgress)  
pgAdmin4
1ht   password: betopass
2nd   password: password

Database personMS, table person

Config dataSource
  application.properties
  spring.datasource.url=...

Create Packages
- controller
- exception
- model
- repository

On model
  person
id
firstName
lastName
email

Add anotations @Entity, @Table, @Id, @GeneratedValue, @Column

On repository package
   @Repository
   interface PersonRepository extends JpaRepository<Table,ID>

On Exception package
    @ResponseStatus(value= HttpStatus.NOT_FOUND)
    ResourceNotFoundException extends RuntimeException 

Add PersonController on Controller package
    Add @RestController
@RequestMapping("/api/v1/")

    inject PersonRepository with @Autowired
    
    add method List<Person> getAllPersons() , @GetMapping("/persons")

Test with browser with localhost:8080/api/v1/pesons
 or with postman 

Create React App 

install node.js
install visual studio code

google create react app, find github.com/facebook/create-react-app where the instrucctions are.

for short
>npx create-react-app react-frontend
>cd react-frontend
>npm start

then it runs on https://localhost:3000/

to sligly modify it, on App.js file modify adding something like
   <h1> My react App is working!</h1>

just to test it.

The React project has a package.json file with 
  - dependencies
  - scripts

The README.me file has the basic instruccions for run and test the app.

On the file node_modules are the dependency packages included and installed for our app.
On public directory we have index.html, in it we have de div root where dinamically react construct all the componenst

On App.js we are going to add jsx files code recomended by react to build components
On index.js we invoke App component which will be rendered.

Add BootStrap 4 in React App

On Visual Code Studio

add bootstrap lib to project
Method 1 by link in html file
- go to google search bootstrap 4 cdn, in page look for link to integrate in index.html, in this case

index.html, this has to be added independently to do the method of npm install bootstrap, at least for the test work for me
...
work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
...   

Method 2 by installing with npm
- in second integrated terminal (powershell)
npm install bootstrap --save         save for integrate in package.json

now we can see it on package.json dependencies

on index.js import 'bootstrap/dist/css/bootstrap.min.css';

Create React List Person Component

initialize git for tracking

-- Creating a listPerson Component in React

Add src/components/ListPersonComponent.jsx

we will use react snippets , googlear react snippets for vs code  -> reactjs code snippets

create the component Person and add it to app.js
type rcc and is sugested create a React class component

The on the method render return on div, we create the code to form the html div, in this case the Person List with classNames styles and fields with data.
  The state has the persons array where the data of persons will be extracted, using map to process each element of the array to be displayed in the table.

Connecting React with List Person RESTAPI

We can use Axios http library, or browser fetch api tool, in this case we'll use axios library to make the http call

npm install axios --save

  Create src/services/PersonService.js with class PersonService and function getPersons
using axios to get the url http://localhost:8080/api/v1/persons

And export the class PersonService to be able to be usen on the component

Then in ListPersonComponent.jsx add method componentDidMount() which is called when the method immediate it is mounted, 
setting the state here and trigger re-rendering.
  This will call service person to get persons as a promise. setting the state with persons array with data from the call to axios backend.

Se hacen ajustes en el controller de Spring boot add @CrossOrigin(origins = "http://localhost:3000")

Creating React Header and Footer Components

Create components HeaderComponent.jsx and FooterComponent.jsx

Configure Routing

we´ll use react routing for this lab, install npm install react-router-dom
import BrowserRouter as Router, Route, and Switch on App.js
Add Router, Switch and Route on div in app.js, just to be displayed the ListPersonComponent in order to the route
  /, /persons, default

Create Add Person REST API

@PostMapping("/persons")
public Person createPerson(@RequestBody Person person) {
   return personRepository.save(person);

Test on Postman with Content-Type application/json, body with json object with person data, check the response

Creating React Add Person Component

Create components/CreatePersonComponent.jsx
create the route to switch to the CreatePersonComponent, this on App.js.

Add button and functionality add person in ListPersonComponent.jsx to push in the router history the desired route.
and bind the object onclick button in the constructor to call addPerson(), use of exact in route

addPerson(){
  this.props.history.push('/add-person');
}

adjust an issue in route / by adding exact to the route. so AddPerson Component can be called.

React Add Person From Handling

On CreatePersonComponent construct the html elements of the form with their respective css bootstrap in order to form
the desired form structure.

  <div className="container">
    ...
       <form>
         ...
         <label>First Name</label>
<input className="form-control" name="firstName" placeholder="First Name"
                value={this.state.firstName} onchange={this.changeFirstNameHandler}/>
         ...
        </form>
     ...
  </div>  

- in constructor initialize state with clean values to elements data of the form, firstName, lastName, email
- construct the elements for html of the from for the elements of data of the form, values taken from state, and onChange
call a function to set the captured values to the state. Bind each function to the class component CreatePersonComponent
in the constructor of the class with .bind(this). The function savePerson create an object person and initialize it with the 
state

Connect React with Add Person REST API

in React service/PersonService.js add method createPerson(Person) and call axios.post(URL, person), and call it 
in CreatePersonComponent.savePerson()


Create Get Person by Id REST API

add controller the mapping with parameter @GetMapping("/persons/{id}")
  ... getPersonById(@PathVariable Long id)
  Person person = personRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("messageX" + id);
  return ResponseEntity.ok(person);

Test on postman 

Create Update Person REST API

   get the person, if exist then asign the new data values and save de person

Create React update Person Component

- On ListPersonComponent.jsx button update will call updatePerson(person.id). which calls the route /update-person/${id}
  this.props.history.push(`/update-person/${id}`

- Add the route with parameter id in App.js
  <Route path="/update-person/:id" component={UpdatePersonComponent}

- Clone de CreatePersonComponent and corresponient parts to UpdatePersonComponent, the Components´s name and the function called by
  the button, This component need to take the id from the list of persons from it where called, this is initialized  in the constructor 
  and the id: this.props.match.params.id.
  On componentDidMount it calls PersonServie.getPersonById to get the person Id Data and assign to the state

  2:19 test the functionality
  In browser check the update form and the console.log to see the person variable updated.

Connecting React with Update Person REST API

- PersonService.updatePerson( person, personid) { return axios.put(PERSON_API_BASE_URL + "/" + personId, person);
- add in UpdatePersonComponent.updatePerson call to PersonService.updatePerson( person, this.state.id).then((res) => {
  this.props.history.push("/persons");
  }

Add & Update Person with Single React Component.

(Reusing CreatePersonComponent for UpdatePersonComponent)

- use the route of add-person this id param, if id negative it is an add if is posititve it is an update.
  or use something === '_add' in url call and do the logic.

-step 1
eliminate de update route on App.js
modify the route of add-person to accept id as parameter "add-person/:id"

-step 2
In CreatePersonComponent.jsx in this.state add id: this.props.match.params.id;
-step 3
in CreatePersonComponent.jsx add componentDidMount(), with PersonService.getPersonById(this.state.id) and set the response
data of Person to the state.
-step 4
Add a conditional in componentDidMount to return if id is negative else do what the step 3 do.
-step 5
In CreatePersonComponent.jsx in savePerson add the condition that when -1 do createPerson else do updatePerson

Creating Delete Person REST API

deleted by id
return map<String, Boolean>
with deleted, true

test with postman

Connecting React with Delete Person API

add PersonService.deletePersonById(id) and on the promise response setState of person with filter the array with the persons
not deleted.

Create React View Person Component

Create a button to see the details of the person because these data are to many for the table.

Create ViewPersonComponent.jsx
Add it to the App.js with route "/view-person/:id"
add button to ListPersonComponent and on click call viewPerson, viewPerson method will push the URL
/view-person/${id}

Design and Show Data on View Person Page

On the state of the viewPersonComponent we initialize the state of the id from the route with
this.state = {
  id: this.props.match.params.id,
  ...

To get the rest of the Person Data we will do a REST API call by id on componentDidMount()



Notes:
POST Create
GET Read
PUT Update/Replace
PATCH Update/Modify
DELETE  Delete

Links:

https://github.com/jalbertomr/springboot-backend

References:

Java Guides, Remesh Fadatare


eot

No hay comentarios:

Publicar un comentario