React JS: Lab#RE01-2
Introduction
Main objectives:
- We’ll be uusing our own
RESTful API
in SpringBoot to create a React app that will display a list of publications - We will use the Axios library to make HTTP requests to the API and retrieve the data in JSON format
- We will display the
publication data
in a table with fields that will depend on the publication type - We will also add a
loading state
to show the user that the app is retrieving data from the API
The lab will demonstrate how to use a RESTful API with React to build a functional web application
Create the app
Follow the same steps as in the Lab-RE01-1 or simply clone the project into another directory.
Remember to install axios
dependency inside the project.
Prepare the Spring Boot API
We’ll be using our Library Management Spring Boot API to retrieve any kind of resource, be it Publications, Users, Librarians, Authors, etc…
Leave it running while testing the React app.
Modify the app
BookList
Now the BookList
component should request data from our SpringBoot API, so some things must be changed.
BookList.jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const BookList = () => {
const [books, setBooks] = useState([]);
const [isLoading, setIsLoading] = useState(true);
// useEffect hook ensures that the BookList component stays connected to the SpringBoot API while displayed on the page
useEffect(() => {
// Define the fetchBooks function (?)
const fetchBooks = async () => {
const response = await axios.get(
'http://localhost:9090/api/publications/books'
);
const booksData = response.data;
setBooks(booksData);
setIsLoading(false);
};
// Invoke the fetchBooks function
fetchBooks();
// TODO: return a clean code function with cleanup code that disconnects from the SpringBoot API
}, []); // No dependencies required nor values from the component used inside of those functions
return (
<>
<h1>Books</h1>
{isLoading ? (
<p>Loading...</p>
) : (
<ul>
{books.map((book) => (
<li key={book.id}>
<strong>Title:</strong> {book.title} <br />
<strong>Year:</strong> {book.publicationDate} <br />
<strong>Author:</strong> {book.author.firstName + " " + book.author.lastName} <br />
<strong>ISBN:</strong> {book.isbn} <br />
<strong>Pages:</strong> {book.pages} <br />
<strong>Genre:</strong> {book.genre} <br />
</li>
))}
</ul>
)}
</>
);
};
export default BookList;
Modify the Spring Boot API
Due to some restrictions related to CORS, we must modify our @RestController
mappings to accept incoming requests from the React app. In order to do so, we’ll add the @CrossOrigin
annotated followed by the origins
parameter with the accepted URLs as values:
PublicationsRestController.java
package com.springbootlab0.approach_1.rest_controllers;
import com.springbootlab0.approach_1.domain.*;
import com.springbootlab0.approach_1.services.PublicationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("api/publications")
public class PublicationsRestController {
@Autowired
PublicationService publicationService;
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("all")
public Iterable<Publication> getAllPublications() {
return publicationService.getAllPublications();
}
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("books")
public Iterable<Publication> getAllBooks() {
return publicationService.getAllBooks();
}
@PostMapping(value = "books/create", consumes = "application/JSON")
public Publication createBook(@RequestBody Book book) {
return publicationService.createPublication(book);
}
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("cds")
public Iterable<Publication> getAllCD() {
return publicationService.getAllCDs();
}
@PostMapping(value = "cds/create", consumes = "application/JSON")
public Publication createCD(@RequestBody CD cd) {
return publicationService.createPublication(cd);
}
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("dvds")
public Iterable<Publication> getAllDVD() {
return publicationService.getAllDVDs();
}
@PostMapping(value = "dvds/create", consumes = "application/JSON")
public Publication createDVD(@RequestBody DVD dvd) {
return publicationService.createPublication(dvd);
}
}
For now, we’ll add http://localhost:3000
as our React app URL, but when going to production, these paths should be parametrized.
Adding CSS to ReactJS
Main objectives:
We’ll add some styling to the React app and use JavaScript to render objects in different fashions:
- Grid
- Card
- Image
- JavaScript
The lab will demonstrate how to use a RESTful API with React and use Components to render objects with CSS
Install dependencies
Install Semantic through npm
Modify functions
Book
Book
will provide the parameters of any stored book. Make sure that Spring Boot API provides the required information.
Same for CD and DVD
Person
Person
will be used to provide the parameters of any LibraryManager. Make sure that Spring Boot API provides the required information.
Create new components
PersonCard
Go to Semantic CSS page and look for the Card component. Analyse what parameters the Card expects and make sure that the SpringBoot API provides them when requesting Books. Then, create your own PersonCard
to format it with the available LibraryMember
attributes:
src/Componets/PersonCard/index.jsx
import { Card, Image } from "semantic-ui-react";
// Props are spreaded prior to pass them to the PersonCard component
const PersonCard = ({image, firstName, lastName, birthDate, role}) => {
return (
<>
<Card style={{ margin: "10px" }}>
<Image src={image} wrapped ui={false} />
{/* Define the Card contents */}
<Card.Content>
<Card.Header>
{lastName}, {firstName}
</Card.Header>
<Card.Meta>Birthdate: {birthDate}</Card.Meta>
<Card.Description>{firstName} is a {role}</Card.Description>
</Card.Content>
</Card>
</>
);
};
export default PersonCard;