React Spring Api | React Js + Spring Boot Rest Api Example Tutorial 인기 답변 업데이트

당신은 주제를 찾고 있습니까 “react spring api – React JS + Spring Boot REST API Example Tutorial“? 다음 카테고리의 웹사이트 https://you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: https://you.tfvp.org/blog. 바로 아래에서 답을 찾을 수 있습니다. 작성자 Java Guides 이(가) 작성한 기사에는 조회수 169,834회 및 좋아요 3,141개 개의 좋아요가 있습니다.

react spring api 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 React JS + Spring Boot REST API Example Tutorial – react spring api 주제에 대한 세부정보를 참조하세요

In this tutorial, we will create a \”single page application\” using React as frontend and spring boot as backend.
What we will build?
—————————————————————
We will build two projects:
1. springboot-backend (server) – To Develop REST API
2. react-frontend (client) – Consume REST API
Read the blog post and get the source code of this tutorial at https://www.javaguides.net/2020/07/react-js-spring-boot-rest-api-example-tutorial.html
If you want to use React Hooks then check out https://youtu.be/iZqp4B2xkS4
#react #springboot#javaguides

react spring api 주제에 대한 자세한 내용은 여기를 참조하세요.

Tutorial | React.js and Spring Data REST

This code has a lot of complexity in it, so we will walk through it, first talking about the annotations and APIs …

+ 여기에 표시

Source: spring.io

Date Published: 7/9/2021

View: 2158

Spring Kết Hợp React – Viblo

List; @RestController @RequestMapping(“/api”) public PostController { private final Logger log …

+ 여기에 보기

Source: viblo.asia

Date Published: 2/13/2021

View: 9691

React Spring – GitHub Pages

Imperative APIs are a great way of animating in response to events, without the need for component state (ie: render-based updates). In this sense, the …

+ 여기에 보기

Source: aleclarson.github.io

Date Published: 2/4/2022

View: 8914

CRUD Application With React and Spring Boot – Baeldung

Calling our Spring Boot API requires setting up our React application’s package.json file to configure a proxy when calling the API. For that, …

+ 여기에 표시

Source: www.baeldung.com

Date Published: 4/8/2022

View: 2348

️ A spring physics based React animation library – GitHub

react-spring is a cross-platform spring-physics first animation library. It’s as simple as: const s = useSpring({ from: …

+ 자세한 내용은 여기를 클릭하십시오

Source: github.com

Date Published: 8/4/2021

View: 5155

Spring Boot + React + MySQL: CRUD example REST APIs

Spring Boot + React + MySQL: CRUD example REST APIs · Create & Setup Spring Boot project · Configure Spring Datasource, JPA, Hibernate · Define …

+ 여기에 더 보기

Source: www.bezkoder.com

Date Published: 11/4/2021

View: 2102

Using React Spring for animation: Context and examples

React Spring takes this up a notch by proving a hook based API which allows you to define and convert data that you would generally pass as …

+ 여기에 표시

Source: blog.logrocket.com

Date Published: 7/29/2021

View: 2059

주제와 관련된 이미지 react spring api

주제와 관련된 더 많은 사진을 참조하십시오 React JS + Spring Boot REST API Example Tutorial. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

React JS + Spring Boot REST API Example Tutorial
React JS + Spring Boot REST API Example Tutorial

주제에 대한 기사 평가 react spring api

  • Author: Java Guides
  • Views: 조회수 169,834회
  • Likes: 좋아요 3,141개
  • Date Published: 2020. 7. 4.
  • Video Url link: https://www.youtube.com/watch?v=5RA5NpxbioI

Can I use Spring with React?

js and Spring Data REST. This tutorial shows a collection of apps that use Spring Data REST and its powerful backend functionality, combined with React’s sophisticated features to build an easy-to-understand UI. Spring Data REST provides a fast way to build hypermedia-powered repositories.

How send data from React to Spring?

Contents
  1. Create an API app with Spring Boot. …
  2. Create a React UI with Create React App.
  3. Call your Spring Boot API and display the results.
  4. Build a React GroupList component.
  5. Add a React GroupEdit component.
  6. Add authentication with Okta. …
  7. Configure Spring Security for React and user identity.

How do you call Spring boot REST service from ReactJS?

1. Develop Spring Boot Backend Application
  1. Create a Spring Boot Application. …
  2. Add maven dependencies. …
  3. Create JPA Entity – User.java. …
  4. Create Spring Data JPA Repository – UserRepository.java. …
  5. Spring Controller with REST API – /api/users. …
  6. Run Spring Boot Application and Test Rest API. …
  7. 1 – Create a React UI with Create React App.

Can I use API in React?

From the API we have target “id”, “name”, “username”, “email” and fetch the data from API endpoints. Below is the stepwise implementation of how we fetch the data from an API in react. We will use the fetch function to get the data from the API. Step by step implementation to fetch data from an api in react.

Is spring a backend or a frontend?

Spring Boot is a backend framework that has become a major player in the enterprise Java ecosystem. It lets Java developers start building web applications quickly, without fuss.

What is REST API in React?

On the other hand, React is one of the most familiar front-end JavaScript libraries used for web applications. Businesses can gain benefits by consuming React REST APIs. It will not only enhance user experience but also allow developers to create large web applications that can change data without reloading the page.

How do I call API in react JS?

How To Make API calls in React Applications
  1. Prerequisites.
  2. Example Project.
  3. Running The API.
  4. Running The React UI.
  5. Project Structure and Development Environment.
  6. Call The API with Fetch.
  7. Call The API with Axios.
  8. Demo.

How fetch API data React?

Fetching data from an API in a React app

While building this type of app, we can create our backend to handle the weather data logic or we can simply make our app communicate with a third-party system that has all the weather information so we only need to render the data.

Is spring MVC still used?

Yes. Whenever someone uses Spring Boot for creating RESTful web services, chances are they are using Spring MVC (part of Spring Web starter, see http://start.spring.io and search Web in dependencies) although Spring has also been offering another web framework, Spring WebFlux.

Is spring boot full stack?

Spring Boot is an awesome Java framework to build RESTful API and Microservices. Lets combine these frameworks and create an awesome java full stack web application.

How integrate REST API react JS?

How To Use an API with ReactJS
  1. Create a Basic Project Structure.
  2. Add React Component.
  3. Add API Calls. Open Up FaiRESTdb API on RapidAPI. Create Database. Create a Model. Grab Code Snippets. Add Snippets to Functions. HTTP Status Codes.

What is the best front end for spring boot?

Top 10 Front-End and Back-end Frameworks for Full-Stack Developers in 2022
  • Spring Boot [Backend + Java] …
  • Angular [Frontend + JavaScript] …
  • Node. …
  • Django [Frontend + Backend + Python] …
  • Flask [Backend + Python] …
  • Bootstrap [Frontend + CSS] …
  • jQuery [Frontend + JavaScript] …
  • Ruby on Rails [Backend + Ruby]

Why is fetch better than Axios?

Without question, some developers prefer Axios over built-in APIs for its ease of use. But many overestimate the need for such a library. The fetch() API is perfectly capable of reproducing the key features of Axios, and it has the added advantage of being readily available in all modern browsers.

What is RESTful API?

RESTful API is an interface that two computer systems use to exchange information securely over the internet. Most business applications have to communicate with other internal and third-party applications to perform various tasks.

Which is better spring or react JS?

React and Spring are primarily classified as “Javascript UI Libraries” and “Frameworks (Full Stack)” tools respectively. “Components”, “Virtual dom” and “Performance” are the key factors why developers consider React; whereas “Java”, “Open source” and “Great community” are the primary reasons why Spring is favored.

How do I run a spring boot and React on the same port?

So, here is a quick guide how to run a react frontend and a spring boot backend on the same port and how to package them as a single jar file. First, create a spring boot project with https://start.spring.io. Add the Web dependency. Set the groupid and artifactid to whatever you want.

Is spring MVC still used?

Yes. Whenever someone uses Spring Boot for creating RESTful web services, chances are they are using Spring MVC (part of Spring Web starter, see http://start.spring.io and search Web in dependencies) although Spring has also been offering another web framework, Spring WebFlux.

Is React better or Angular?

React is better than Angular due to it’s virtual DOM implementation and rendering optimizations. Migrating between React’s versions is quite easy, too; you don’t need to install updates one by one, as in the case of Angular. Finally, with React, developers have myriads of existing solutions they can use.

React.js and Spring Data REST

This section shows how to get a bare-bones Spring Data REST application up and running quickly. Then it shows how to build a simple UI on top of it by using Facebook’s React.js toolset.

This demo uses Java 8, Maven Project, and the latest stable release of Spring Boot. It also uses React.js coded in ES6 . This will give you a clean, empty project. From there, you can add the various files shown explicitly in this section and/or borrow from the repository listed earlier.

If you want to do it yourself, visit https://start.spring.io and pick the following dependencies:

Feel free to grab the code from this repository and follow along.

This entity is used to track employee information — in this case, their names and job descriptions.

Domain objects form the cornerstone of any Spring Data REST-based application. In this section, you will build an application to track the employees for a company. Kick that off by creating a data type, as follows:

The system uses well accepted, industry standard protocols, such as HTTP verbs, standardized media types, and IANA-approved link names .

Spring Data REST addresses how simple this problem can be if some assumptions are made:

In the beginning, there was data. And it was good. But then people wanted to access the data through various means. Over the years, people cobbled together lots of MVC controllers, many using Spring’s powerful REST support. But doing over and over cost a lot of time.

That is all that is needed! In fact, you need not even annotate interface if it is top-level and visible. If you use your IDE and open up CrudRepository , you will find a collection of pre-defined methods.

Another key piece of a Spring Data REST application is a corresponding repository definition, as follows:

That is how we can write an empty interface and inherit already built save, find, and delete operations.

One of the biggest, most powerful features of Spring Data is its ability to write JPA queries for you. This not only cuts down on your development time, but it also reduces the risk of bugs and errors. Spring Data looks at the name of methods in a repository class and figures out the operations you need, including saving, deleting, and finding.

To work with this application, you need to pre-load it with some data, as follows:

By default, Spring Data REST hosts a root collection of links at / . Because you will host a web UI on that path, you need to change the root URI, as follows:

Assuming the previous class as well as your Maven build file were generated from https://start.spring.io , you can now launch it either by running that main() method inside your IDE or by typing ./mvnw spring-boot:run on the command line. ( mvnw.bat for Windows users).

The last step needed to get a fully operational REST API off the ground is to write a public static void main method by using Spring Boot, as follows:

You can also PUT , PATCH , and DELETE , as shown in this related guide . For now, though, we will move on to building a slick UI.

That is all well and good, but you are probably itching to create some new entries. The following command (shown with its output) does so:

Little has changed here, except that there is no need for the _embedded wrapper since there is only the domain object.

You can decide to view that one employee if you wish. The following command (shown with its output) does so:

Along with the data you pre-loaded earlier, a _links attribute with a self link is included. This is the canonical link for that particular employee. What is canonical? It means “free of context”. For example, the same user could be fetched through /api/orders/1/processor , in which the employee is associated with processing a particular order. Here, there is no relationship to other entities.

At this stage, you are viewing the entire collection of employees.

You can further dig into this service by navigating the employees link. The following command (shown with its output) does so:

profile is an IANA-standard relation and points to discoverable metadata about the entire service. We explore this in a later section.

employees points to an aggregate root for the employee objects defined by the EmployeeRepository interface.

When you ping the root node, you get back a collection of links wrapped in a HAL-formatted JSON document .

With the application running, you can check things out on the command line by using cURL (or any other tool you like). The following command (shown with its output) lists the links in the application:

Spring Boot makes it super simple to stand up a custom web page. First, you need a Spring MVC controller, as follows:

You may also wonder where that bundle.js file came from. The way it is built is shown in the next section.

The key part in this template is the

component in the middle. It is where you will direct React to plug in the rendered output.

You are using Thymeleaf, although you will not really use many of its features. To get started you need an index page, as follows:

Since you are using webpack to assemble things, go ahead and fetch the modules you need:

With all that in place, you can focus on the React bits, which are fetched after the DOM is loaded. It is broken down into parts, as follows:

For more details on how each of these JavaScript tools operates, please read their corresponding reference docs.

It hooks into the babel engine, using both es2015 and react presets, in order to compile ES6 React code into a format able to be run in any standard browser.

Compile ALL of the JavaScript bits into ./src/main/resources/static/built/bundle.js , which is a JavaScript equivalent to a Spring Boot uber JAR. All your custom code AND the modules pulled in by the require() calls are stuffed into this file.

Creates sourcemaps so that, when you are debugging JS code in the browser, you can link back to original source code.

Defines the entry point as ./src/main/js/app.js . In essence, app.js (a module you will write shortly) is the proverbial public static void main() of our JavaScript application. webpack must know this in order to know what to launch when the final bundle is loaded by the browser.

To build the JavaScript code you’ll use later, you need to define a build file for webpack , as follows:

babel: To write your JavaScript code using ES6 and compile it into ES5 to run in the browser

What modules are installed? JavaScript developers typically use npm to build up a package.json file, such as the following:

These steps are run in sequence, essentially installing node.js, downloading JavaScript modules, and building the JS bits.

The webpack command will execute webpack binary, which compiles all the JavaScript code based on webpack.config.js .

The npm command will execute the npm binary with the provided argument ( install ). This installs the modules defined in package.json .

The install-node-and-npm command will install node.js and its package management tool, npm , into the target folder. (This ensures the binaries are NOT pulled under source control and can be cleaned out with clean ).

This section contains the barebones information to get the JavaScript bits off the ground. While you can install all of JavaScripts command line tools, you need not do so — at least, not yet. Instead, all you need to do is add the following to your pom.xml build file:

Diving into React

React is based on defining components. Often, one component can hold multiple instances of another in a parent-child relationship. This concept can extend to several layers.

To start things off, it is very handy to have a top level container for all components. (This will become more evident as you expand upon the code throughout this series.) Right now, you only have the employee list. But you might need some other related components later on, so start with the following:

Example 12. src/main/js/app.js – App component class App extends React.Component { (1) constructor(props) { super(props); this.state = {employees: []}; } componentDidMount() { (2) client({method: ‘GET’, path: ‘/api/employees’}).done(response => { this.setState({employees: response.entity._embedded.employees}); }); } render() { (3) return ( ) } } 1 class App extends React.Component{…​} is the method that creates a React component. 2 componentDidMount is the API invoked after React renders a component in the DOM. 3 render is the API that “draws” the component on the screen.

In React, uppercase is the convention for naming components.

In the App component, an array of employees is fetched from the Spring Data REST backend and stored in this component’s state data.

React components have two types of data: state and properties. State is data that the component is expected to handle itself. It is also data that can fluctuate and change. To read the state, you use this.state . To update it, you use this.setState() . Every time this.setState() is called, React updates the state, calculates a diff between the previous state and the new state, and injects a set of changes to the DOM on the page. This results in fast and efficient updates to your UI. The common convention is to initialize state with all your attributes empty in the constructor. Then you look up data from the server by using componentDidMount and populating your attributes. From there on, updates can be driven by user action or other events. Properties encompass data that is passed into the component. Properties do NOT change but are instead fixed values. To set them, you assign them to attributes when creating a new component, as you will soon see.

JavaScript does not lock down data structures as other languages do. You can try to subvert properties by assigning values, but this does not work with React’s differential engine and should be avoided.

In this code, the function loads data through client , a Promise-compliant instance of rest.js. When it is done retrieving from /api/employees , it then invokes the function inside done() and sets the state based on its HAL document ( response.entity._embedded.employees ). See the structure of curl /api/employees earlier and see how it maps onto this structure.

When the state is updated, the render() function is invoked by the framework. The employee state data is included in the creation of the React component as an input parameter.

The following listing shows the definition for an EmployeeList :

Example 13. src/main/js/app.js – EmployeeList component class EmployeeList extends React.Component{ render() { const employees = this.props.employees.map(employee => ); return (

{employees}

First Name Last Name Description

) } }

Using JavaScript’s map function, this.props.employees is transformed from an array of employee records into an array of React components (which you will see a little later).

Consider the following listing:

The preceding listing creates a new React component (note the uppercase format) with two properties: key and data. These are supplied with values from employee._links.self.href and employee .

Whenever you work with Spring Data REST, the self link is the key for a given resource. React needs a unique identifier for child nodes, and _links.self.href is perfect.

Finally, you return an HTML table wrapped around the array of employees built with mapping, as follows:

{employees}

First Name Last Name Description

This simple layout of state, properties, and HTML shows how React lets you declaratively create a simple and easy-to-understand component.

Does this code contain both HTML and JavaScript? Yes, this is JSX. There is no requirement to use it. React can be written using pure JavaScript, but the JSX syntax is quite terse. Thanks to rapid work on the Babel.js, the transpiler provides both JSX and ES6 support all at once. JSX also includes bits and pieces of ES6. The one used in this code is the arrow function. It avoids creating a nested function() with its own scoped this and avoids needing a self variable. Worried about mixing logic with your structure? React’s APIs encourage nice, declarative structure combined with state and properties. Instead of mixing a bunch of unrelated JavaScript and HTML, React encourages building simple components with small bits of related state and properties that work well together. It lets you look at a single component and understand the design. Then they are easy to combine together for bigger structures.

Next, you need to actually define what an is, as follows:

Example 14. src/main/js/app.js – Employee component class Employee extends React.Component{ render() { return (

{this.props.employee.firstName} {this.props.employee.lastName} {this.props.employee.description}

) } }

This component is very simple. It has a single HTML table row wrapped around the employee’s three properties. The property itself is this.props.employee . Notice how passing in a JavaScript object makes it easy to pass along data fetched from the server.

Because this component does not manage any state nor deal with user input, there is nothing else to do. This might tempt you to cram it into the up above. Do not do it! Splitting your app up into small components that each do one job will make it easier to build up functionality in the future.

The last step is to render the whole thing, as follows:

Example 15. src/main/js/app.js – rendering code ReactDOM.render( , document.getElementById(‘react’) )

React.render() accepts two arguments: a React component you defined as well as a DOM node to inject it into. Remember how you saw the

item earlier from the HTML page? This is where it gets picked up and plugged in.

With all this in place, re-run the application ( ./mvnw spring-boot:run ) and visit http://localhost:8080. The following image shows the updated application:

You can see the initial employee loaded up by the system.

Remember using cURL to create new entries? Do that again with the following command:

curl -X POST localhost:8080/api/employees -d “{\”firstName\”: \”Bilbo\”, \”lastName\”: \”Baggins\”, \”description\”: \”burglar\”}” -H “Content-Type:application/json”

Refresh the browser, and you should see the new entry:

Spring Kết Hợp React

Giới thiệu

Spring là một Framwork nền tảng Java nó được tạo ra để thay thế cho các công nghệ cũ cồng kềnh như EJB, dựa trên 2 nguyên tắc chính là Dependency Injection và Aspect Oriented Programing và dựa trên mô hình sử dụng POJO Spring trở nên gon nhẹ và linh hoạt cho các dự án. React là một thư việc JavaScript được phát triển bởi Facebook giúp cho việc phát triển trở nên đơn giản và trực quan hơn cho người dùng. Việc kết hợp giữa Spring và React giúp ích rất nhiều cho việc phát triển ứng dụng

Step By Step Demo

Trước tiên chúng ta cần tạo ra một project cho Spring, Ở đây mình sử dụng Spring boot và sử dụng tool build Gradle. Bạn có thể dễ dàng thực hiện việc này bằng cách lên trang start.spring.io trên trang này chúng ta cũng có thể chọn cho mình những dependencies tương ứng mà chúng ta mong muốn sẽ sử dụng trong project. Ở đây mình sử dụng các dependencies Web, H2, JPA, Lombok tương tự như hình ảnh Sau khi import vào IDE vào file build.gradle để kiểm tra chúng ta có thể thấy danh sách dependencies sau:

dependencies { implementation ‘org.springframework.boot:spring-boot-starter-data-jpa’ implementation ‘org.springframework.boot:spring-boot-starter-web’ runtimeOnly ‘com.h2database:h2’ compileOnly ‘org.projectlombok:lombok’ testImplementation ‘org.springframework.boot:spring-boot-starter-test’ }

Theo các step của demo này mình sẽ thực hiện việc tạo ra một danh sách các bài Post (bao gồm tiêu đề và hình ảnh) và các chức năng thêm sửa xóa

Xây dựng API bằng Spring boot

Tạo package model và thêm class Post.java

package com.example.demo.model; import lombok.*; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Getter @Setter @NoArgsConstructor @RequiredArgsConstructor @Entity @Table(name = “post”) public class Post { @Id @GeneratedValue private Long id; @NonNull private String content; }

Để init dữ liệu ban đầu ta tạo ra một class Initializer như sau

package com.example.demo.init; import com.example.demo.model.Post; import com.example.demo.repository.PostRepository; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.util.stream.Stream; @Component public class Initializer implements CommandLineRunner { private final PostRepository postRepository; public Initializer(PostRepository postRepository) { this.postRepository = postRepository; } @Override public void run(String… strings) { Stream.of(“Post 1”, “Post 2”, “Post 3”, “Post 4”, “Post 5”) .forEach(content -> postRepository.save(new Post(content))); postRepository.findAll().forEach(System.out::println); } }

Sau khi run server chúng ta có thể thấy dữ liệu được in ra ở log

Thêm PostController class để xử lý việc gọi api

package com.example.demo.controller; import com.example.demo.model.Post; import com.example.demo.service.PostService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.net.URI; import java.net.URISyntaxException; import java.util.List; @RestController @RequestMapping(“/api”) public class PostController { private final Logger log = LoggerFactory.getLogger(PostController.class); @Autowired PostService postService; @GetMapping(“/post/list”) List list() { return postService.listPost(); } @GetMapping(“/post/{id}”) ResponseEntity getPost(@PathVariable Long postId) { return postService.findById(postId); } @PostMapping(“/post”) ResponseEntity createPost(@Valid @RequestBody Post post) throws URISyntaxException { Post newPost = postService.savePost(post); return ResponseEntity.created(new URI(“/api/post” + newPost.getId())).body(newPost); } @PutMapping(“/post”) ResponseEntity updatePost(@Valid @RequestBody Post post) { Post newPost = postService.savePost(post); return ResponseEntity.ok().body(newPost); } @DeleteMapping(“/post/{id}”) ResponseEntity deletePost(@PathVariable Long postId) { postService.deletePost(postId); return ResponseEntity.ok().build(); } }

Thêm service để xử lý logic cho các thao tác CRUD Interface PostService

package com.example.demo.service; import com.example.demo.model.Post; import org.springframework.http.ResponseEntity; import java.util.List; public interface PostService { List listPost(); ResponseEntity findById(Long postId); Post savePost(Post post); void deletePost(Long postId); }

và class implement Service

package com.example.demo.service; import com.example.demo.model.Post; import com.example.demo.repository.PostRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class PostServiceImpl implements PostService { @Autowired private PostRepository postRepository; @Override public ResponseEntity findById(Long postId) { Optional postOptional = postRepository.findById(postId); return postOptional.map(post -> ResponseEntity.ok().body(post)).orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND)); } @Override public List listPost() { return postRepository.findAll(); } @Override public Post savePost(Post post) { return postRepository.save(post); } @Override public void deletePost(Long postId) { postRepository.deleteById(postId); } }

Thêm repository để thực hiện việc tương tác với DB

package com.example.demo.repository; import com.example.demo.model.Post; import org.springframework.data.jpa.repository.JpaRepository; public interface PostRepository extends JpaRepository { }

Xây dựng React để tạo giao diện và đổ dữ liệu

Ở trong thư mục dữ liệu thực hiện lệnh

yarn create react-app app

Ở bước này có thể bạn sẽ gặp một số lỗi liên quan đến node version, hãy cài đặt phiên bản node phù hợp theo console log lỗi thông báo và chạy lại lệnh là được. sau đó vào thư mục app mới được tạo ra

cd app

sau đó cài thêm Boostrap, cookie hỗ trợ cho React, React Router, and Reactstrap

import css cho file index.js

import ‘bootstrap/dist/css/bootstrap.min.css’;

Ở App.js chúng ta gọi dữ liệu từ API của Spring boot

import React, { Component } from ‘react’; import logo from ‘./logo.svg’; import ‘./App.css’; class App extends Component { state = { isLoading: true, posts: [] }; async componentDidMount() { const response = await fetch(‘/api/post/list’); const body = await response.json(); this.setState({ posts: body, isLoading: false }); } render() { const {posts, isLoading} = this.state; if (isLoading) { return

Loading…

; } return (

logo

Post List

{posts.map(post =>

{post.content}

)}

); } } export default App;

Để ủy quyền từ /api tới http://localhost:8080/api thêm cài đặt proxy vào app/package.json. thêm “proxy”: “http://localhost:8080” ngay sau chỗ khai báo cho scripts như sau

“scripts”: {…}, “proxy”: “http://localhost:8080”,

Bây giờ chúng ta start app bằng lệnh yarn start thì cổng 3000 sẽ mở lên và gọi dữ liệu từ api/post/list ra để hiển thị kết quả sẽ như sau

Thay việc đặt các dữ liệu trong App.js thành một file mới cho việc hiển thị danh sách bài post như sau

import React, { Component } from ‘react’; import { Button, ButtonGroup, Container, Table } from ‘reactstrap’; import AppNavbar from ‘./AppNavbar’; import { Link } from ‘react-router-dom’; class PostList extends Component { constructor(props) { super(props); this.state = {posts: [], isLoading: true}; this.remove = this.remove.bind(this); } componentDidMount() { this.setState({isLoading: true}); fetch(‘api/posts’) .then(response => response.json()) .then(data => this.setState({posts: data, isLoading: false})); } async remove(id) { await fetch(`/api/post/${id}`, { method: ‘DELETE’, headers: { ‘Accept’: ‘application/json’, ‘Content-Type’: ‘application/json’ } }).then(() => { let updatedPosts = […this.state.posts].filter(i => i.id !== id); this.setState({posts: updatedPosts}); }); } render() { const {posts, isLoading} = this.state; if (isLoading) { return

Loading…

; } const postList = posts.map(post => { return

{post.content}

}); return (

Post List

{postList}

Name Actions

); } } export default PostList;

Để tạo navigation chúng ta thêm class AppNavbar.js

import React, { Component } from ‘react’; import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from ‘reactstrap’; import { Link } from ‘react-router-dom’; export default class AppNavbar extends Component { constructor(props) { super(props); this.state = {isOpen: false}; this.toggle = this.toggle.bind(this); } toggle() { this.setState({ isOpen: !this.state.isOpen }); } render() { return Home ; } }

Thêm class Home.js để hiển thị mặc định khi mới load vào trang

import React, { Component } from ‘react’; import ‘./App.css’; import AppNavbar from ‘./AppNavbar’; import { Link } from ‘react-router-dom’; import { Button, Container } from ‘reactstrap’; class Home extends Component { render() { return (

); } } export default Home;

Thêm class PostEdit để thực hiện việc thêm và chỉnh sửa bài post

import React, { Component } from ‘react’; import { Link, withRouter } from ‘react-router-dom’; import { Button, Container, Form, FormGroup, Input, Label } from ‘reactstrap’; import AppNavbar from ‘./AppNavbar’; class PostEdit extends Component { emptyItem = { content: ” }; constructor(props) { super(props); this.state = { item: this.emptyItem }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } async componentDidMount() { if (this.props.match.params.id !== ‘new’) { const post = await (await fetch(`/api/post/${this.props.match.params.id}`)).json(); this.setState({item: post}); } } handleChange(event) { const target = event.target; const value = target.value; const content = target.content; let item = {…this.state.item}; item[content] = value; this.setState({item}); } async handleSubmit(event) { event.preventDefault(); const {item} = this.state; await fetch(‘/api/post’, { method: (item.id) ? ‘PUT’ : ‘POST’, headers: { ‘Accept’: ‘application/json’, ‘Content-Type’: ‘application/json’ }, body: JSON.stringify(item), }); this.props.history.push(‘/posts’); } render() { const {item} = this.state; const title =

{item.id ? ‘Edit Post’ : ‘Add Post’}

; return

{title}
{‘ ‘}

} } export default withRouter(PostEdit);

Chỉnh sửa lại class App.js thay thế bằng các Route

import React, { Component } from ‘react’; import logo from ‘./logo.svg’; import ‘./App.css’; import Home from ‘./Home’; import { BrowserRouter as Router, Route, Switch } from ‘react-router-dom’; import PostList from ‘./PostList’; import PostEdit from ‘./PostEdit’; class App extends Component { render() { return ( ) } } export default App;

Sau khi hoàn thành chúng ta run app lên và có thể thực hiện các thao tác CRUD Màn hình chính

Vào danh sách

Chỉnh sửa

Thêm mới

Tài liệu tham khảo

https://developer.okta.com/blog/2018/07/19/simple-crud-react-and-spring-boot https://www.tutorialspoint.com/reactjs/

React Spring

This page explains every feature introduced in v9.

For breaking changes, go here.

🎨 The examples with graphics are editable.

Platform packages

While you can still import react-spring for the web version, you can now use @react-spring/web if you’d prefer to avoid installing the wrapper package for every other supported platform. You can use Yarn aliases to make it seamless.

yarn add react – spring@npm : @react – spring / web@ 9.0 .0 – rc . 1

Every supported platform has its own package, which depends on @react-spring/core . The react-spring package re-exports the package of every supported platform, which means you can import react-spring/native like you could in v8.

The react-spring/universal module has been replaced by @react-spring/core .

Platform interop

In v9, you can use multiple “render targets” on the same page. This means you can animate 3d objects with @react-spring/three while animating DOM elements with @react-spring/web on the same page! 🤩

Click here for a demo.

UMD bundle

Currently, only the @react-spring/web package has a UMD bundle.

Click here for the latest version.

https : / / cdn . jsdelivr . net / npm / @react – spring / web@next / index . umd . min . js

Unified API

In the past two major versions, the “Render Props API” and “Hooks API” were provided by separate modules. In fact, each API had its own implementation of the internal Controller class, which was bad for maintenance.

import { useSpring } from ‘react-spring’ import { Spring } from ‘react-spring/renderprops’

The new version unifies these APIs into a single module!

import { Spring , useSpring } from ‘react-spring’

Revamped types

TypeScript support has undergone a facelift.

Most types have been renamed, modified, or removed.

Not yet 100% stable. Please report any rough edges! ✌️

Any questions can be directed here.

🚧 More type documentation coming soon.

The useTransition rework

Learn about the new useTransition on the Breaking Changes page.

Concurrent mode

Support for React’s concurrent mode has been added.

Please report any issues you may find. 😇

Dependency arrays

Every hook except useChain now supports a deps argument, which is an array exactly like what useEffect takes.

Whenever a dependency is changed, the update will be processed and thus the animation will be updated. But otherwise, updates are ignored when all dependencies are unchanged.

When a dependency array is passed, the useSpring and useSprings hooks each return an animate function.

const [ style , animate ] = useSpring ( { x : 0 , y : 0 } , [ ] ) useEffect ( ( ) => { animate ( { x : 100 , y : 100 } ) } , [ ] )

Shorthand style props

In the web version only, you can avoid the boilerplate of using the to function to combine multiple animated values into a transform string like you had to do in v8.

Instead, you can try defining an animated value in the style object using one of the following shorthand props:

x , y , z

, , translate , translateX , translateY , translate3d

, , , rotate , rotateX , rotateY , rotate3d

, , , scale , scaleX , scaleY , scale3d

, , , skew , skewX , skewY

, , matrix , matrix3d

const { x , y } = useSpring ( { x : 0 , y : 0 } ) import { to } from ‘react-spring’ const transform = to ( [ x , y ] , ( x , y ) => ` translate( ${ x } px, ${ y } px) ` ) return < a . div style = { { transform } } / > return < a . div style = { { x , y } } / >

These shorthand props will be added to @react-spring/native in the future. For now, they only exist in @react-spring/web .

The loop prop

Use loop: true to repeat an animation.

The loop function

Pass a function to be called after each loop. Return true to continue looping, or false to stop.

The loop function can also return a loop object, which is described in the next section. This is useful when you want to decide the next loop animation right after the previous loop is finished.

The loop object

Define a loop object to customize the loop animation separately from the initial animation. It may contain any of the useSpring props. For example, if reverse: true is used, the loop animation will reverse on each loop.

Inherited props

The loop object is always merged into a copy of the props object it was defined in. The following example shows a loop animation that inherits its config prop.

⚠️ Notice how the loop doesn’t run more than once. That’s because some props are never inherited. These props include default , reset , and reverse .

To loop the animation, try adding reset: true to the loop prop in the above example. Alternatively, you could add from: { x: 0 } to get the same effect.

Lastly, try adding config: { friction: 5 } to the loop object. This overrides the inherited config.duration with a springy animation.

Dynamic goals

The FrameValue class (inherited by SpringValue and Interpolation ) allows for animations toward or from an observable FluidValue object. You can make any library work like this with react-spring by following this guide.

Try using immediate: true to make rotateZ stick to its FluidValue instead of animating toward it.

The from prop can also be a FluidValue , but it only caches the FluidValue ‘s current value when first animated and when the reset prop is true. In other words, nothing will happen if the from value is changed during an animation.

The cancel prop

When true , the cancel prop stops the animation of every animated value owned by the Controller that receives it.

The following example never animates, because cancel is always true.

useSpring ( { cancel : true , from : { x : 0 } , to : { x : 100 } , } )

Once the cancel prop turns from true to false , the declared animation will resume or reset, depending on the given props.

The cancel prop even prevents delayed updates. 😎

const [ style , animate ] = useSpring ( ( ) => ( { x : 0 } ) ) const onClick = ( ) => { animate ( { x : 100 , delay : 500 } ) animate ( { cancel : true } ) }

Specific keys

To cancel the animation of specific keys, you can pass a single key, an array of keys, or a (key: string) => boolean function.

cancel : ‘x’ , cancel : [ ‘x’ , ‘y’ ] , cancel : key => key !== ‘x’ ,

The reset and immediate props support these same types.

The pause prop

The pause prop literally freezes animations in time.

When used in a declarative update, the declared animation is paused until the pause prop equals false again. Then the animation will continue from its current value.

The following example will pause the animation while your mouse is over it. (Note: The useHover hook is theoretical)

const isHovering = useHover ( ) useSpring ( { pause : isHovering , from : { x : 0 } , to : { x : 100 } , loop : true , } )

Animation results

The onRest prop receives an AnimationResult object when called. It contains the following properties:

value: any The current value when the animation ended.

The current value when the animation ended. target: object The object being animated (either a SpringValue or Controller ).

The object being animated (either a or ). finished?: boolean Equals true when the animation finished before being stopped or cancelled.

Equals true when the animation finished before being stopped or cancelled. cancelled?: boolean Equals true when the animation was cancelled.

The promise returned by the ref API’s start method is resolved with an AnimationResult object, as well as the start method of the SpringValue and Controller classes.

Config props

The config prop existed in v8.x, but v9.x brings a few improvements.

The config prop can now be partially updated.

const { x } = useSpring ( { from : { x : 0 } , config : { frequency : 1 } , } ) useEffect ( ( ) => { x . start ( { config : { velocity : 0 } } ) x . start ( { config : { friction : 20 } } ) } , [ ] )

Additions

The following props have been added:

frequency?: number The natural frequency (in seconds), which dictates the number of bounces per second when no damping exists. When defined, tension is derived from this, and friction is derived from tension and damping .

damping?: number The damping ratio, which dictates how the spring slows down. Set to 0 to never slow down. Set to 1 to slow down without bouncing. Between 0 and 1 is for you to explore. Only works when frequency is defined. Defaults to 1 .

round?: number While animating, round to the nearest multiple of this number. The from and to values are never rounded, as well as any value passed to the set method of an animated value.

bounce?: number When above zero, the spring will bounce instead of overshooting when exceeding its goal value. Its velocity is multiplied by -1 + bounce whenever its current value equals or exceeds its goal. For example, setting bounce to 0.5 chops the velocity in half on each bounce, in addition to any friction.

progress?: number When used with duration , it decides how far into the easing function to start from. The duration itself is unaffected. Defaults to 0 , which means “start from the beginning”. Setting to 1+ makes an immediate animation. Setting to 0.5 means “start from the middle of the easing function”. Any number >= 0 and <= 1 makes sense here. restVelocity?: number The smallest velocity before the animation is considered to be "not moving". When undefined, precision is used instead. Default props The default prop lets you set the default value of certain props defined in the same update. For the declarative API, this prop is true by default. In the following example, the onRest handler is inherited by every update passed to animate , except when a call has its own onRest prop defined. useSpring ( { to : async animate => { … } , onRest : ( ) => { … } } )

Imperative updates can use default: true to set default props. When an async to prop is defined by an imperative update, it will inherit props from the imperative update like this:

useSpring ( { from : { x : 0 } , to : async animate => { await animate ( { to : [ { x : 100 } , { x : 0 } ] , config : { tension : 100 } , } ) } , } )

Default props are inherited while an update is being processed by the internal diffing algorithm within the SpringValue#_merge method.

For example, both the ref prop and the animate function will inherit the default props defined below (in the useSpring props function).

const ref = useRef ( ) const [ { x } , animate ] = useSpring ( ( ) => ( { x : 0 , onRest : ( ) => { … } , ref , } ) ) useEffect ( async ( ) => { await ref . current . start ( { x : 100 } ) await animate ( { x : 0 } ) } , [ ] )

Compatible props

In the last example, only the onRest prop is inherited, because only some props can have a default value.

The following props can have default values:

cancel

config

immediate

onChange

onDelayEnd

onProps

onRest

onStart

pause

The default object

In addition to passing default: true , you can also pass an object instead. Only the props defined in your default object will be saved for future updates.

In this example, we are setting true as the default value of immediate . This affects all future animations owned by the useSpring call, whether or not they are declarative or imperative.

const { x } = useSpring ( { x : 0 , default : { immediate : true } , } ) useEffect ( ( ) => { x . start ( 100 ) } )

Event props

Props like onRest can now be defined on a per-key basis.

useSpring ( { from : { x : 0 , y : 0 } , onRest : { x : ( ) => console . log ( ‘x.onRest’ ) , y : ( ) => console . log ( ‘y.onRest’ ) , } , } )

Whenever an event prop is called, it’s first wrapped with unstable_batchedUpdates (exported by React), which ensures multiple setState calls won’t cause components to rerender more times than is necessary. This prevents several tricky edge cases.

React to finished delays

The onDelayEnd prop is called for every non-cancelled update, after its delay is finished, but before the props are merged. It receives a props object and the affected SpringValue object.

useSpring ( { onDelayEnd ( props , spring ) { console . log ( ‘onDelayEnd:’ , props , spring ) } , } )

Inspect your props

The onProps prop is called for every update that isn’t prevented.

It receives a props object and the affected SpringValue object. It can be useful when debugging an animation.

The onProps prop is called immediately after all props have been merged into the animation of the affected SpringValue object, but before the first frame of an animation initiated by the props.

useSpring ( { onProps ( props , spring ) { console . log ( ‘onProps:’ , { props , spring , … spring . animation , } ) } , } )

The SpringContext component

Modify animations within the given children , but only the animations created by the hook API (eg: useSpring ) or renderprops API (eg: ) are affected. Animations created with new SpringValue() or new Controller() are unaffected.

< SpringContext cancel = { true } > < App / > < / SpringContext >

The following props are supported:

cancel?: boolean

config?: SpringConfig

immediate?: boolean

pause?: boolean

The SpringContext component can be used anywhere.

The most common use case is pausing or finishing animations on a page while it is temporarily invisible to the user. For example, the user may navigate away from a modal with animated content that stays mounted when hidden.

Nested context

Descendants of a SpringContext component can use SpringContext to selectively override any props forced by another SpringContext .

In the example below, only Page2 can play its animations. Pretend this element tree is rendered more dynamically, and this code is a static representation.

< SpringContext pause = { true } > < Page1 / > < SpringContext pause = { false } > < Page2 / > < / SpringContext > < Page3 / > < / SpringContext >

Every nested SpringContext inherits the values of the nearest SpringContext ancestor.

The skipAnimation global

When true , all animations are finished immediately. The requestAnimationFrame loop is skipped entirely. Any onRest callbacks are still invoked.

import { Globals } from ‘react-spring’ Globals . assign ( { skipAnimation : true } )

Combine skipAnimation with prefers-reduced-motion to gracefully disable or reduce the motion of your animations. The react-reduce-motion package can help with that.

import { Globals } from ‘react-spring’ import { useReduceMotion } from ‘react-reduce-motion’ const prefersReducedMotion = useReduceMotion ( ) useEffect ( ( ) => { Globals . assign ( { skipAnimation : prefersReducedMotion , } ) } , [ prefersReducedMotion ] )

The SpringValue class

Imperative APIs are a great way of animating in response to events, without the need for component state (ie: render-based updates). In this sense, the SpringValue class is a welcome addition to react-spring .

It wraps around an Animated node, the type of object you passed to animated components in v8. Now you’ll be passing SpringValue objects, which manage their own Animation state (separate from any Controller object).

new SpringValue(props)

Create an animated value. Any type is valid, but only certain types are actually animated.

The props argument can be either..

a to value

value or a set of useSpring props.

Types that cannot be animated are basically immediate: true animations. Such types include: a boolean , a display string like “none” , etc.

The animatable types are:

number s new SpringValue ( 0 )

string s with numbers new SpringValue ( ‘0px 10px’ ) new SpringValue ( ‘rgba(0, 0, 255, 1)’ )

named colors new SpringValue ( ‘red’ )

and arrays of the preceding types new SpringValue ( [ 0 , ‘1em’ ] )

Methods

get(): T

Get the current value.

const value = spring . get ( )

set(value): this

Set the current value, replace the goal value, and stop animating.

spring . set ( 1 )

Add an update to the queue array. All updates in the queue are applied at the same time.

const delays = [ 0 , 100 , 300 ] for ( const delay of delays ) { spring . update ( { x : delay } ) } spring . start ( )

⚠️ This method may be deprecated soon.

start(): Promise

Process the queue array and replace it with an empty array.

The returned Promise resolves after every animation triggered by the queue array has either finished or been cancelled.

await spring . start ( )

The awaited value is an AnimationResult object.

The AnimationResult type has the following properties:

value: T

spring: SpringValue

finished?: boolean

cancelled?: boolean

start(props): Promise

Process the given props object.

The returned promise is resolved after the animation is finished or cancelled. If a start call triggers no animation, the promise resolves immediately.

await spring . start ( { from : 0 , to : 1 } )

start(queue): Promise

Process the given array of updates.

The returned promise resolves to an AnimationResult object whose:

finished property is only true when every animation triggered by the queue was finished before being stopped or cancelled.

cancelled property is only false when all updates in the queue were never cancelled.

await spring . start ( [ { from : 0 } , { to : 10 } , { to : 20 , delay : 1000 } , ] )

finish(): this

Jump to the goal value immediately.

The onStart prop is called whenever finish is called before the first frame. The onRest prop is called with finished: true as expected.

spring . finish ( )

finish(value): this

Jump to the given value immediately, and call the onStart and onRest props the same way .finish() does.

spring . finish ( 100 )

Fluid values (eg: other SpringValue objects) can also be passed.

stop(): this

Stop animating and cancel any delayed updates.

The goal value is replaced with the current value.

spring . stop ( )

reset(): this

Restart the animation using its cached from and to values.

spring . reset ( )

Equivalent to a .start({ reset: true }) call.

advance(dt: number): boolean

Advance the current animation by the given dt (in milliseconds).

You will probably never call this.

spring . advance ( 1000 / 60 )

is(phase: string): void

Check for the given phase.

if ( spring . is ( ‘PAUSED’ ) ) { return }

Valid phases include:

CREATED The spring has never animated since being created.

The spring has never animated since being created. IDLE The spring is done animating.

The spring is done animating. ACTIVE The spring is animating.

The spring is animating. PAUSED The spring was animating but is now paused.

The spring was animating but is now paused. DISPOSED The spring can no longer animate.

Properties

key?: string

The name given to the SpringValue object by its owner.

For Controller objects, the key of each SpringValue is the property name from either the to or from object prop.

When defined, the to prop can be an object with this key defined as a property.

spring . key = ‘foo’ spring . start ( { to : { foo : ‘180deg’ } } )

get idle(): boolean

Returns true when both:

the current phase is anything but ACTIVE

no async to prop is active

Put simply, it’s true when not animating.

get goal(): T

The end value of the current animation.

get velocity(): number | number[]

The velocity of the current animation.

animation: Animation

The animation descriptor.

The queue of pending updates.

pmndrs/react-spring: ✌️ A spring physics based React animation library

A spring-physics first animation library

giving you flexible tools to confidently cast your ideas

react-spring is a cross-platform spring-physics first animation library.

It’s as simple as:

const styles = useSpring ( { from : { opacity : 0 } , to : { opacity : 1 } } ) < animated . div style = { styles } / >

Just a small bit about us:

Cross-Platform : We support react-dom , react-native , react-three-fiber , react-konva & react-zdog .

: We support , , , & . Versatile : Be declarative with your animations or if you prefer, imperative.

: Be declarative with your animations or if you prefer, imperative. Spring-Physics First: By default animation use springs for fluid interactivity, but we support durations with easings as well.

There’s a lot more to be had! Give it a try and find out.

Getting Started

⚡️ Jump Start

# Install the entire library npm install react-spring # or just install your specific target (recommended) npm install @react-spring/web

import { animated , useSpring } from ‘@react-spring/web’ const FadeIn = ( { isVisible , children } ) => { const styles = useSpring ( { opacity : isVisible ? 1 : 0 , y : isVisible ? 0 : 24 } ) return < animated . div style = { styles } > { children } < / animated . div > }

It’s as simple as that to create scroll-in animations when value of isVisible is toggled.

📖 Documentation and Examples

More documentation on the project can be found here.

Pages contain their own examples which you can check out there, or open in codesandbox for a more in-depth view!

📣 What others say

Used by

And many others…

Backers

Thank you to all our backers! 🙏 If you want to join them here, then consider contributing to our Opencollective.

Contributors

This project exists thanks to all the people who contribute.

React.js and Spring Data REST

This section shows how to get a bare-bones Spring Data REST application up and running quickly. Then it shows how to build a simple UI on top of it by using Facebook’s React.js toolset.

This demo uses Java 8, Maven Project, and the latest stable release of Spring Boot. It also uses React.js coded in ES6 . This will give you a clean, empty project. From there, you can add the various files shown explicitly in this section and/or borrow from the repository listed earlier.

If you want to do it yourself, visit https://start.spring.io and pick the following dependencies:

Feel free to grab the code from this repository and follow along.

This entity is used to track employee information — in this case, their names and job descriptions.

Domain objects form the cornerstone of any Spring Data REST-based application. In this section, you will build an application to track the employees for a company. Kick that off by creating a data type, as follows:

The system uses well accepted, industry standard protocols, such as HTTP verbs, standardized media types, and IANA-approved link names .

Spring Data REST addresses how simple this problem can be if some assumptions are made:

In the beginning, there was data. And it was good. But then people wanted to access the data through various means. Over the years, people cobbled together lots of MVC controllers, many using Spring’s powerful REST support. But doing over and over cost a lot of time.

That is all that is needed! In fact, you need not even annotate interface if it is top-level and visible. If you use your IDE and open up CrudRepository , you will find a collection of pre-defined methods.

Another key piece of a Spring Data REST application is a corresponding repository definition, as follows:

That is how we can write an empty interface and inherit already built save, find, and delete operations.

One of the biggest, most powerful features of Spring Data is its ability to write JPA queries for you. This not only cuts down on your development time, but it also reduces the risk of bugs and errors. Spring Data looks at the name of methods in a repository class and figures out the operations you need, including saving, deleting, and finding.

To work with this application, you need to pre-load it with some data, as follows:

By default, Spring Data REST hosts a root collection of links at / . Because you will host a web UI on that path, you need to change the root URI, as follows:

Assuming the previous class as well as your Maven build file were generated from https://start.spring.io , you can now launch it either by running that main() method inside your IDE or by typing ./mvnw spring-boot:run on the command line. ( mvnw.bat for Windows users).

The last step needed to get a fully operational REST API off the ground is to write a public static void main method by using Spring Boot, as follows:

You can also PUT , PATCH , and DELETE , as shown in this related guide . For now, though, we will move on to building a slick UI.

That is all well and good, but you are probably itching to create some new entries. The following command (shown with its output) does so:

Little has changed here, except that there is no need for the _embedded wrapper since there is only the domain object.

You can decide to view that one employee if you wish. The following command (shown with its output) does so:

Along with the data you pre-loaded earlier, a _links attribute with a self link is included. This is the canonical link for that particular employee. What is canonical? It means “free of context”. For example, the same user could be fetched through /api/orders/1/processor , in which the employee is associated with processing a particular order. Here, there is no relationship to other entities.

At this stage, you are viewing the entire collection of employees.

You can further dig into this service by navigating the employees link. The following command (shown with its output) does so:

profile is an IANA-standard relation and points to discoverable metadata about the entire service. We explore this in a later section.

employees points to an aggregate root for the employee objects defined by the EmployeeRepository interface.

When you ping the root node, you get back a collection of links wrapped in a HAL-formatted JSON document .

With the application running, you can check things out on the command line by using cURL (or any other tool you like). The following command (shown with its output) lists the links in the application:

Spring Boot makes it super simple to stand up a custom web page. First, you need a Spring MVC controller, as follows:

You may also wonder where that bundle.js file came from. The way it is built is shown in the next section.

The key part in this template is the

component in the middle. It is where you will direct React to plug in the rendered output.

You are using Thymeleaf, although you will not really use many of its features. To get started you need an index page, as follows:

Since you are using webpack to assemble things, go ahead and fetch the modules you need:

With all that in place, you can focus on the React bits, which are fetched after the DOM is loaded. It is broken down into parts, as follows:

For more details on how each of these JavaScript tools operates, please read their corresponding reference docs.

It hooks into the babel engine, using both es2015 and react presets, in order to compile ES6 React code into a format able to be run in any standard browser.

Compile ALL of the JavaScript bits into ./src/main/resources/static/built/bundle.js , which is a JavaScript equivalent to a Spring Boot uber JAR. All your custom code AND the modules pulled in by the require() calls are stuffed into this file.

Creates sourcemaps so that, when you are debugging JS code in the browser, you can link back to original source code.

Defines the entry point as ./src/main/js/app.js . In essence, app.js (a module you will write shortly) is the proverbial public static void main() of our JavaScript application. webpack must know this in order to know what to launch when the final bundle is loaded by the browser.

To build the JavaScript code you’ll use later, you need to define a build file for webpack , as follows:

babel: To write your JavaScript code using ES6 and compile it into ES5 to run in the browser

What modules are installed? JavaScript developers typically use npm to build up a package.json file, such as the following:

These steps are run in sequence, essentially installing node.js, downloading JavaScript modules, and building the JS bits.

The webpack command will execute webpack binary, which compiles all the JavaScript code based on webpack.config.js .

The npm command will execute the npm binary with the provided argument ( install ). This installs the modules defined in package.json .

The install-node-and-npm command will install node.js and its package management tool, npm , into the target folder. (This ensures the binaries are NOT pulled under source control and can be cleaned out with clean ).

This section contains the barebones information to get the JavaScript bits off the ground. While you can install all of JavaScripts command line tools, you need not do so — at least, not yet. Instead, all you need to do is add the following to your pom.xml build file:

Diving into React

React is based on defining components. Often, one component can hold multiple instances of another in a parent-child relationship. This concept can extend to several layers.

To start things off, it is very handy to have a top level container for all components. (This will become more evident as you expand upon the code throughout this series.) Right now, you only have the employee list. But you might need some other related components later on, so start with the following:

Example 12. src/main/js/app.js – App component class App extends React.Component { (1) constructor(props) { super(props); this.state = {employees: []}; } componentDidMount() { (2) client({method: ‘GET’, path: ‘/api/employees’}).done(response => { this.setState({employees: response.entity._embedded.employees}); }); } render() { (3) return ( ) } } 1 class App extends React.Component{…​} is the method that creates a React component. 2 componentDidMount is the API invoked after React renders a component in the DOM. 3 render is the API that “draws” the component on the screen.

In React, uppercase is the convention for naming components.

In the App component, an array of employees is fetched from the Spring Data REST backend and stored in this component’s state data.

React components have two types of data: state and properties. State is data that the component is expected to handle itself. It is also data that can fluctuate and change. To read the state, you use this.state . To update it, you use this.setState() . Every time this.setState() is called, React updates the state, calculates a diff between the previous state and the new state, and injects a set of changes to the DOM on the page. This results in fast and efficient updates to your UI. The common convention is to initialize state with all your attributes empty in the constructor. Then you look up data from the server by using componentDidMount and populating your attributes. From there on, updates can be driven by user action or other events. Properties encompass data that is passed into the component. Properties do NOT change but are instead fixed values. To set them, you assign them to attributes when creating a new component, as you will soon see.

JavaScript does not lock down data structures as other languages do. You can try to subvert properties by assigning values, but this does not work with React’s differential engine and should be avoided.

In this code, the function loads data through client , a Promise-compliant instance of rest.js. When it is done retrieving from /api/employees , it then invokes the function inside done() and sets the state based on its HAL document ( response.entity._embedded.employees ). See the structure of curl /api/employees earlier and see how it maps onto this structure.

When the state is updated, the render() function is invoked by the framework. The employee state data is included in the creation of the React component as an input parameter.

The following listing shows the definition for an EmployeeList :

Example 13. src/main/js/app.js – EmployeeList component class EmployeeList extends React.Component{ render() { const employees = this.props.employees.map(employee => ); return (

{employees}

First Name Last Name Description

) } }

Using JavaScript’s map function, this.props.employees is transformed from an array of employee records into an array of React components (which you will see a little later).

Consider the following listing:

The preceding listing creates a new React component (note the uppercase format) with two properties: key and data. These are supplied with values from employee._links.self.href and employee .

Whenever you work with Spring Data REST, the self link is the key for a given resource. React needs a unique identifier for child nodes, and _links.self.href is perfect.

Finally, you return an HTML table wrapped around the array of employees built with mapping, as follows:

{employees}

First Name Last Name Description

This simple layout of state, properties, and HTML shows how React lets you declaratively create a simple and easy-to-understand component.

Does this code contain both HTML and JavaScript? Yes, this is JSX. There is no requirement to use it. React can be written using pure JavaScript, but the JSX syntax is quite terse. Thanks to rapid work on the Babel.js, the transpiler provides both JSX and ES6 support all at once. JSX also includes bits and pieces of ES6. The one used in this code is the arrow function. It avoids creating a nested function() with its own scoped this and avoids needing a self variable. Worried about mixing logic with your structure? React’s APIs encourage nice, declarative structure combined with state and properties. Instead of mixing a bunch of unrelated JavaScript and HTML, React encourages building simple components with small bits of related state and properties that work well together. It lets you look at a single component and understand the design. Then they are easy to combine together for bigger structures.

Next, you need to actually define what an is, as follows:

Example 14. src/main/js/app.js – Employee component class Employee extends React.Component{ render() { return (

{this.props.employee.firstName} {this.props.employee.lastName} {this.props.employee.description}

) } }

This component is very simple. It has a single HTML table row wrapped around the employee’s three properties. The property itself is this.props.employee . Notice how passing in a JavaScript object makes it easy to pass along data fetched from the server.

Because this component does not manage any state nor deal with user input, there is nothing else to do. This might tempt you to cram it into the up above. Do not do it! Splitting your app up into small components that each do one job will make it easier to build up functionality in the future.

The last step is to render the whole thing, as follows:

Example 15. src/main/js/app.js – rendering code ReactDOM.render( , document.getElementById(‘react’) )

React.render() accepts two arguments: a React component you defined as well as a DOM node to inject it into. Remember how you saw the

item earlier from the HTML page? This is where it gets picked up and plugged in.

With all this in place, re-run the application ( ./mvnw spring-boot:run ) and visit http://localhost:8080. The following image shows the updated application:

You can see the initial employee loaded up by the system.

Remember using cURL to create new entries? Do that again with the following command:

curl -X POST localhost:8080/api/employees -d “{\”firstName\”: \”Bilbo\”, \”lastName\”: \”Baggins\”, \”description\”: \”burglar\”}” -H “Content-Type:application/json”

Refresh the browser, and you should see the new entry:

Use React and Spring Boot to Build a Simple CRUD App

React was designed to make it painless to create interactive UIs. Its state management is efficient and only updates components when your data changes. Component logic is written in JavaScript, meaning you can keep state out of the DOM and create encapsulated components.

Developers like CRUD (create, read, update, and delete) apps because they show a lot of the base functionality you need when creating an app. Once you have the basics of CRUD completed in an app, most of the client-server plumbing is finished, and you can move on to implementing the necessary business logic.

Today, I’ll show you how to create a basic CRUD app with Spring Boot and React. In this tutorial, I’ll use the OAuth 2.0 Authorization Code flow and package the React app in the Spring Boot app for production. At the same time, I’ll show you how to keep React’s productive workflow for developing locally.

You will need Java 11 and Node 16 installed to complete this tutorial.

Table of Contents

Create an API app with Spring Boot

I’m a frequent speaker at conferences and user groups around the world. My favorite user groups to speak at are Java User Groups (JUGs). I’ve been a Java developer for almost 20 years and love the Java community. One of my good friends, James Ward, said doing a JUG Tour was one of his favorite developer advocate activities back in the day. I recently took his advice and traded overseas conferences for JUG meetups in the US.

Why am I telling you this? Because I thought it’d be fun to create a “JUG Tours” app today that allows you to create/edit/delete JUGs and view upcoming events.

To begin, navigate to start.spring.io and make the following selections:

Group: com.okta.developer

Artifact: jugtours

Dependencies: JPA , H2 , Web , Lombok

Click Generate Project, expand jugtours.zip after downloading, and open the project in your favorite IDE.

TIP: If you’re using IntelliJ IDEA or Spring Tool Suite, you can also use Spring Initializr when creating a new project.

Add a JPA domain model

The first thing you’ll need to do is to create a domain model that’ll hold your data. At a high level, there’s a Group that represents the JUG, an Event that has a many-to-one relationship with Group , and a User that has a one-to-many relationship with Group .

Create a src/main/java/com/okta/developer/jugtours/model directory and a Group.java class in it.

package com.okta.developer.jugtours.model ; import lombok.Data ; import lombok.NoArgsConstructor ; import lombok.NonNull ; import lombok.RequiredArgsConstructor ; import javax.persistence.* ; import java.util.Set ; @Data @NoArgsConstructor @RequiredArgsConstructor @Entity @Table ( name = “user_group” ) public class Group { @Id @GeneratedValue private Long id ; @NonNull private String name ; private String address ; private String city ; private String stateOrProvince ; private String country ; private String postalCode ; @ManyToOne ( cascade = CascadeType . PERSIST ) private User user ; @OneToMany ( fetch = FetchType . EAGER , cascade = CascadeType . ALL ) private Set < Event > events ; }

Create an Event.java class in the same package.

package com.okta.developer.jugtours.model ; import lombok.AllArgsConstructor ; import lombok.Builder ; import lombok.Data ; import lombok.NoArgsConstructor ; import javax.persistence.Entity ; import javax.persistence.GeneratedValue ; import javax.persistence.Id ; import javax.persistence.ManyToMany ; import java.time.Instant ; import java.util.Set ; @Data @NoArgsConstructor @AllArgsConstructor @Builder @Entity public class Event { @Id @GeneratedValue private Long id ; private Instant date ; private String title ; private String description ; @ManyToMany private Set < User > attendees ; }

And a User.java class.

package com.okta.developer.jugtours.model ; import lombok.AllArgsConstructor ; import lombok.Data ; import lombok.NoArgsConstructor ; import javax.persistence.Entity ; import javax.persistence.Id ; @Data @NoArgsConstructor @AllArgsConstructor @Entity public class User { @Id private String id ; private String name ; private String email ; }

Create a GroupRepository.java to manage the group entity.

package com.okta.developer.jugtours.model ; import org.springframework.data.jpa.repository.JpaRepository ; import java.util.List ; public interface GroupRepository extends JpaRepository < Group , Long > { Group findByName ( String name ); }

To load some default data, create an Initializer.java class in the com.okta.developer.jugtours package.

package com.okta.developer.jugtours ; import com.okta.developer.jugtours.model.Event ; import com.okta.developer.jugtours.model.Group ; import com.okta.developer.jugtours.model.GroupRepository ; import org.springframework.boot.CommandLineRunner ; import org.springframework.stereotype.Component ; import java.time.Instant ; import java.util.Collections ; import java.util.stream.Stream ; @Component class Initializer implements CommandLineRunner { private final GroupRepository repository ; public Initializer ( GroupRepository repository ) { this . repository = repository ; } @Override public void run ( String … strings ) { Stream . of ( “Seattle JUG” , “Denver JUG” , “Dublin JUG” , “London JUG” ). forEach ( name -> repository . save ( new Group ( name )) ); Group djug = repository . findByName ( “Seattle JUG” ); Event e = Event . builder (). title ( “Micro Frontends for Java Developers” ) . description ( “JHipster now has microfrontend support!” ) . date ( Instant . parse ( “2022-09-13T17:00:00.000Z” )) . build (); djug . setEvents ( Collections . singleton ( e )); repository . save ( djug ); repository . findAll (). forEach ( System . out :: println ); } }

TIP: If your IDE has issues with Event.builder() , you need to turn on annotation processing and/or install the Lombok plugin. I had to uninstall/reinstall the Lombok plugin in IntelliJ IDEA to get things to work.

If you start your app (using ./mvnw spring-boot:run ) …

… it will fail because Spring Boot 2.7.0 forces H2 v2.0. The H2 2.0 ecosystem doesn’t seem like it’s quite ready for prime time, so I recommend you downgrade to H2 version 1.4.200 in your pom.xml .

com.h2database h2 runtime 1.4.200

Then, mvn spring-boot:run should result in something like:

Group(id=1, name=Seattle JUG, address=null, city=null, stateOrProvince=null, country=null, postalCode=null, user=null, events=[Event(id=5, date=2022-09-13T17:00:00Z, title=Micro Frontends for Java Developers, description=JHipster now has microfrontend support!, attendees=[])]) Group(id=2, name=Denver JUG, address=null, city=null, stateOrProvince=null, country=null, postalCode=null, user=null, events=[]) Group(id=3, name=Dublin JUG, address=null, city=null, stateOrProvince=null, country=null, postalCode=null, user=null, events=[]) Group(id=4, name=London JUG, address=null, city=null, stateOrProvince=null, country=null, postalCode=null, user=null, events=[])

Add a GroupController.java class (in src/main/java/…/jugtours/web/GroupController.java ) that allows you to CRUD groups.

package com.okta.developer.jugtours.web ; import com.okta.developer.jugtours.model.Group ; import com.okta.developer.jugtours.model.GroupRepository ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.springframework.http.HttpStatus ; import org.springframework.http.ResponseEntity ; import org.springframework.web.bind.annotation.* ; import javax.validation.Valid ; import java.net.URI ; import java.net.URISyntaxException ; import java.util.Collection ; import java.util.Optional ; @RestController @RequestMapping ( “/api” ) class GroupController { private final Logger log = LoggerFactory . getLogger ( GroupController . class ); private GroupRepository groupRepository ; public GroupController ( GroupRepository groupRepository ) { this . groupRepository = groupRepository ; } @GetMapping ( “/groups” ) Collection < Group > groups () { return groupRepository . findAll (); } @GetMapping ( “/group/{id}” ) ResponseEntity getGroup ( @PathVariable Long id ) { Optional < Group > group = groupRepository . findById ( id ); return group . map ( response -> ResponseEntity . ok (). body ( response )) . orElse ( new ResponseEntity <>( HttpStatus . NOT_FOUND )); } @PostMapping ( “/group” ) ResponseEntity < Group > createGroup ( @Valid @RequestBody Group group ) throws URISyntaxException { log . info ( “Request to create group: {}” , group ); Group result = groupRepository . save ( group ); return ResponseEntity . created ( new URI ( “/api/group/” + result . getId ())) . body ( result ); } @PutMapping ( “/group/{id}” ) ResponseEntity < Group > updateGroup ( @Valid @RequestBody Group group ) { log . info ( “Request to update group: {}” , group ); Group result = groupRepository . save ( group ); return ResponseEntity . ok (). body ( result ); } @DeleteMapping ( “/group/{id}” ) public ResponseEntity deleteGroup ( @PathVariable Long id ) { log . info ( “Request to delete group: {}” , id ); groupRepository . deleteById ( id ); return ResponseEntity . ok (). build (); } }

Add the following dependency to your pom.xml to fix compilation errors:

jakarta.validation jakarta.validation-api 2.0.2

If you stop and start your server app and hit http://localhost:8080/api/groups with your browser, or a command line client, you should see the list of groups.

You can create, read, update, and delete groups with the following HTTPie commands.

http POST :8080/api/group name = ‘Utah JUG’ city = ‘Salt Lake City’ country = USA http :8080/api/group/6 http PUT :8080/api/group/6 id = 6 name = ‘Utah JUG’ address = ‘On the slopes’ http DELETE :8080/api/group/6

Create a React UI with Create React App

Create React App is a command line utility that generates React projects for you. It’s a convenient tool because it also offers commands to build and optimize your project for production. It uses webpack under the covers to build everything.

Create a new project in the jugtours directory with npx .

npx create-react-app@5 app

After the app creation process completes, navigate into the app directory and install Bootstrap, cookie support for React, React Router, and Reactstrap.

cd app npm i bootstrap@5 react-cookie@4 react-router-dom@6 reactstrap@9

You’ll use Bootstrap’s CSS and Reactstrap’s components to make the UI look better, especially on mobile phones. If you’d like to learn more about Reactstrap, see reactstrap.github.io. It has extensive documentation on Reactstrap’s various components and their use.

Add Bootstrap’s CSS file as an import in app/src/index.js .

import ‘ bootstrap/dist/css/bootstrap.min.css ‘ ;

Call your Spring Boot API and display the results

Modify app/src/App.js to use the following code that calls /api/groups and displays the list in the UI.

import React , { useEffect , useState } from ‘ react ‘ ; import logo from ‘ ./logo.svg ‘ ; import ‘ ./App.css ‘ ; const App = () => { const [ groups , setGroups ] = useState ([]); const [ loading , setLoading ] = useState ( false ); useEffect (() => { setLoading ( true ); fetch ( ‘ api/groups ‘ ) . then ( response => response . json ()) . then ( data => { setGroups ( data ); setLoading ( false ); }) }, []); if ( loading ) { return < p > Loading… ; } return ( < div className = "App" > < header className = "App-header" > < img src = { logo } className = "App-logo" alt = "logo" /> < div className = "App-intro" > < h2 > JUG List { groups . map ( group => < div key = { group . id } > { group . name } ) } ); } export default App ;

TIP: I learned a lot about React Hooks from Build a CRUD App in React with Hooks by Tania Rascia.

To proxy from /api to http://localhost:8080/api , add a proxy setting to app/package.json .

“scripts” : { … } , “proxy” : “http://localhost:8080” ,

To learn more about proxying API requests, see Create React App’s documentation.

Make sure Spring Boot is running, then run npm start in your app directory. You should see the list of default groups.

Build a React GroupList component

React is all about components, and you don’t want to render everything in your main App , so create app/src/GroupList.js and populate it with the following JavaScript.

import React , { useEffect , useState } from ‘ react ‘ ; import { Button , ButtonGroup , Container , Table } from ‘ reactstrap ‘ ; import AppNavbar from ‘ ./AppNavbar ‘ ; import { Link } from ‘ react-router-dom ‘ ; const GroupList = () => { const [ groups , setGroups ] = useState ([]); const [ loading , setLoading ] = useState ( false ); useEffect (() => { setLoading ( true ); fetch ( ‘ api/groups ‘ ) . then ( response => response . json ()) . then ( data => { setGroups ( data ); setLoading ( false ); }) }, []); const remove = async ( id ) => { await fetch ( `/api/group/ ${ id } ` , { method : ‘ DELETE ‘ , headers : { ‘ Accept ‘ : ‘ application/json ‘ , ‘ Content-Type ‘ : ‘ application/json ‘ } }). then (() => { let updatedGroups = [… groups ]. filter ( i => i . id !== id ); setGroups ( updatedGroups ); }); } if ( loading ) { return < p > Loading… ; } const groupList = groups . map ( group => { const address = ` ${ group . address || ” } ${ group . city || ” } ${ group . stateOrProvince || ” } ` ; return < tr key = { group . id } > < td style = { { whiteSpace : ' nowrap ' } } > { group . name } < td > { address } < td > { group . events . map ( event => { return < div key = { event . id } > { new Intl . DateTimeFormat ( ‘ en-US ‘ , { year : ‘ numeric ‘ , month : ‘ long ‘ , day : ‘ 2-digit ‘ }). format ( new Date ( event . date )) } : { event . title } }) } < td > < ButtonGroup > < Button size = "sm" color = "primary" tag = { Link } to = { " /groups/ " + group . id } > Edit < Button size = "sm" color = "danger" onClick = { () => remove ( group . id ) } > Delete }); return ( < div > < AppNavbar /> < Container fluid > < div className = "float-end" > < Button color = "success" tag = { Link } to = "/groups/new" > Add Group < h3 > My JUG Tour < Table className = "mt-4" > < thead > < tr > < th width = "20%" > Name < th width = "20%" > Location < th > Events < th width = "10%" > Actions < tbody > { groupList } ); }; export default GroupList ;

Create AppNavbar.js in the same directory to establish a common UI feature between components.

import React , { useState } from ‘ react ‘ ; import { Collapse , Nav , Navbar , NavbarBrand , NavbarToggler , NavItem , NavLink } from ‘ reactstrap ‘ ; import { Link } from ‘ react-router-dom ‘ ; const AppNavbar = () => { const [ isOpen , setIsOpen ] = useState ( false ); return ( < Navbar color = "dark" dark expand = "md" > < NavbarBrand tag = { Link } to = "/" > Home < NavbarToggler onClick = { () => { setIsOpen ( ! isOpen ) } } /> < Collapse isOpen = { isOpen } navbar > < Nav className = "justify-content-end" style = { { width : " 100% " } } navbar > < NavItem > < NavLink href = "https://twitter.com/oktadev" > @oktadev < NavItem > < NavLink href = "https://github.com/oktadev/okta-spring-boot-react-crud-example" > GitHub ); }; export default AppNavbar ;

Create app/src/Home.js to serve as the landing page for your app.

import React from ‘ react ‘ ; import ‘ ./App.css ‘ ; import AppNavbar from ‘ ./AppNavbar ‘ ; import { Link } from ‘ react-router-dom ‘ ; import { Button , Container } from ‘ reactstrap ‘ ; const Home = () => { return ( < div > < AppNavbar /> < Container fluid > < Button color = "link" >< Link to = "/groups" > Manage JUG Tour ); } export default Home ;

Also, change app/src/App.js to use React Router to navigate between components.

import React from ‘ react ‘ ; import ‘ ./App.css ‘ ; import Home from ‘ ./Home ‘ ; import { BrowserRouter as Router , Route , Routes } from ‘ react-router-dom ‘ ; import GroupList from ‘ ./GroupList ‘ ; import GroupEdit from ‘ ./GroupEdit ‘ ; const App = () => { return ( < Router > < Routes > < Route exact path = "/" element = { < Home /> } /> < Route path = '/groups' exact = { true } element = { < GroupList /> } /> ) } export default App ;

To make your UI a bit more spacious, add a top margin to Bootstrap’s container classes in app/src/App.css .

nav + .container , nav + .container-fluid { margin-top : 20px ; }

Your React app should update itself as you make changes, and you should see a screen like the following at http://localhost:3000 .

Click on Manage JUG Tour and you should see a list of the default groups.

It’s great that you can see your Spring Boot API’s data in your React app, but it’s no fun if you can’t edit it!

Add a React GroupEdit component

Create app/src/GroupEdit.js and use useEffect() to fetch the group resource with the ID from the URL.

import React , { useEffect , useState } from ‘ react ‘ ; import { Link , useNavigate , useParams } from ‘ react-router-dom ‘ ; import { Button , Container , Form , FormGroup , Input , Label } from ‘ reactstrap ‘ ; import AppNavbar from ‘ ./AppNavbar ‘ ; const GroupEdit = () => { const initialFormState = { name : ” , address : ” , city : ” , stateOrProvince : ” , country : ” , postalCode : ” }; const [ group , setGroup ] = useState ( initialFormState ); const navigate = useNavigate (); const { id } = useParams (); useEffect (() => { if ( id !== ‘ new ‘ ) { fetch ( `/api/group/ ${ id } ` ) . then ( response => response . json ()) . then ( data => setGroup ( data )); } }, [ id , setGroup ]); const handleChange = ( event ) => { const { name , value } = event . target setGroup ({ … group , [ name ]: value }) } const handleSubmit = async ( event ) => { event . preventDefault (); await fetch ( ‘ /api/group ‘ + ( group . id ? ‘ / ‘ + group . id : ” ), { method : ( group . id ) ? ‘ PUT ‘ : ‘ POST ‘ , headers : { ‘ Accept ‘ : ‘ application/json ‘ , ‘ Content-Type ‘ : ‘ application/json ‘ }, body : JSON . stringify ( group ) }); setGroup ( initialFormState ); navigate ( ‘ /groups ‘ ); } const title = < h2 > { group . id ? ‘ Edit Group ‘ : ‘ Add Group ‘ } ; return (< div > < AppNavbar /> < Container > { title } < Form onSubmit = { handleSubmit } > < FormGroup > < Label for = "name" > Name < Input type = "text" name = "name" id = "name" value = { group . name || '' } onChange = { handleChange } autoComplete = "name" /> < FormGroup > < Label for = "address" > Address < Input type = "text" name = "address" id = "address" value = { group . address || '' } onChange = { handleChange } autoComplete = "address-level1" /> < FormGroup > < Label for = "city" > City < Input type = "text" name = "city" id = "city" value = { group . city || '' } onChange = { handleChange } autoComplete = "address-level1" /> < div className = "row" > < FormGroup className = "col-md-4 mb-3" > < Label for = "stateOrProvince" > State/Province < Input type = "text" name = "stateOrProvince" id = "stateOrProvince" value = { group . stateOrProvince || '' } onChange = { handleChange } autoComplete = "address-level1" /> < FormGroup className = "col-md-5 mb-3" > < Label for = "country" > Country < Input type = "text" name = "country" id = "country" value = { group . country || '' } onChange = { handleChange } autoComplete = "address-level1" /> < FormGroup className = "col-md-3 mb-3" > < Label for = "country" > Postal Code < Input type = "text" name = "postalCode" id = "postalCode" value = { group . postalCode || '' } onChange = { handleChange } autoComplete = "address-level1" /> < FormGroup > < Button color = "primary" type = "submit" > Save { ‘ ‘ } < Button color = "secondary" tag = { Link } to = "/groups" > Cancel ) }; export default GroupEdit ;

The useParams() hook is used to grab the ID from the URL and useNavigate() allows you to navigate back to the GroupList after adding or saving a group.

Modify app/src/App.js to import GroupEdit and specify a path to it.

import GroupEdit from ‘ ./GroupEdit ‘ ; const App = () => { return ( < Router > < Routes > … < Route path = '/groups/:id' element = { < GroupEdit /> } /> ) }

Now you should be able to add and edit groups!

Add authentication with Okta

It’s pretty cool to build a CRUD app, but it’s even cooler to build a secure one. To achieve that, you’ll want to add authentication so users have to log in before viewing/modifying groups. To make this simple, you can use Okta’s API for OIDC. At Okta, our goal is to make identity management a lot easier, more secure, and more scalable than what you’re used to. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

Authenticate and authorize your users

Store data about your users

Perform password-based and social login

Secure your application with multi-factor authentication

And much more! Check out our product documentation

Are you sold? Register for a forever-free developer account, and when you’re done, come on back so you can learn more about building secure apps with Spring Boot!

Spring Security + OIDC

Spring Security added OIDC support in its 5.0 release. Since then, they’ve made quite a few improvements and simplified its required configuration. Add the Okta Spring Boot starter to do OIDC authentication.

com.okta.spring okta-spring-boot-starter 2.1.5

This dependency is a thin wrapper around Spring Security’s OAuth and encapsulates the following dependencies:

org.springframework.boot spring-boot-starter-security org.springframework.security spring-security-config org.springframework.security spring-security-oauth2-client org.springframework.security spring-security-oauth2-jose

Create an OIDC app in Okta

Install the Okta CLI and run okta login . Then, run okta apps create . Select the default app name, or change it as you see fit. Choose Web and press Enter.

Select Okta Spring Boot Starter. Then, change the Redirect URI to http://localhost:8080/login/oauth2/code/okta and use http://localhost:3000,http://localhost:8080 for the Logout Redirect URI.

What does the Okta CLI do? The Okta CLI will create an OIDC Web App in your Okta Org. It will add the redirect URIs you specified and grant access to the Everyone group. You will see output like the following when it’s finished: Okta application configuration has been written to: /path/to/app/src/main/resources/application.properties Open src/main/resources/application.properties to see the issuer and credentials for your app. okta.oauth2.issuer = https://dev-133337.okta.com/oauth2/default okta.oauth2.client-id = 0oab8eb55Kb9jdMIr5d6 okta.oauth2.client-secret = NEVER-SHOW-SECRETS NOTE: You can also use the Okta Admin Console to create your app. See Create a Spring Boot App for more information.

Configure Spring Security for React and user identity

To make Spring Security React-friendly, create a SecurityConfiguration.java file in src/main/java/…/jugtours/config . Create the config directory and put this class in it.

package com.okta.developer.jugtours.config ; import org.springframework.context.annotation.Bean ; import org.springframework.security.config.annotation.web.builders.HttpSecurity ; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity ; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter ; import org.springframework.security.web.SecurityFilterChain ; import org.springframework.security.web.csrf.CookieCsrfTokenRepository ; import org.springframework.security.web.savedrequest.HttpSessionRequestCache ; import org.springframework.security.web.savedrequest.RequestCache ; import org.springframework.security.web.savedrequest.SimpleSavedRequest ; import javax.servlet.http.HttpServletRequest ; import javax.servlet.http.HttpServletResponse ; @EnableWebSecurity public class SecurityConfiguration { @Bean public SecurityFilterChain filterChain ( HttpSecurity http ) throws Exception { http . authorizeHttpRequests (( authz ) -> authz . antMatchers ( “/**/*.{js,html,css}” ). permitAll () . antMatchers ( “/” , “/api/user” ). permitAll () . anyRequest (). authenticated () ) . csrf (( csrf ) -> csrf . csrfTokenRepository ( CookieCsrfTokenRepository . withHttpOnlyFalse ()) ) . oauth2Login (); return http . build (); } @Bean public RequestCache refererRequestCache () { return new HttpSessionRequestCache () { @Override public void saveRequest ( HttpServletRequest request , HttpServletResponse response ) { String referrer = request . getHeader ( “referer” ); if ( referrer != null ) { request . getSession (). setAttribute ( “SPRING_SECURITY_SAVED_REQUEST” , new SimpleSavedRequest ( referrer )); } } }; } }

This class has a lot going on, so let me explain a few things. The RequestCache bean overrides the default request cache. It saves the referrer header (misspelled referer in real life), so Spring Security can redirect back to it after authentication. The referrer-based request cache comes in handy when you’re developing React on http://localhost:3000 and want to be redirected back there after logging in.

@Bean public RequestCache refererRequestCache () { return new HttpSessionRequestCache () { @Override public void saveRequest ( HttpServletRequest request , HttpServletResponse response ) { String referrer = request . getHeader ( “referer” ); if ( referrer != null ) { request . getSession (). setAttribute ( “SPRING_SECURITY_SAVED_REQUEST” , new SimpleSavedRequest ( referrer )); } } }; }

Configuring CSRF (cross-site request forgery) protection with CookieCsrfTokenRepository.withHttpOnlyFalse() means that the XSRF-TOKEN cookie won’t be marked HTTP-only, so React can read it and send it back when it tries to manipulate data.

The antMatchers lines define what URLs are allowed for anonymous users. You will soon configure things so your React app is served up by your Spring Boot app, hence the reason for allowing web files and “/”. You might also notice an exposed /api/user path. Create src/main/java/…/jugtours/web/UserController.java and populate it with the following code. This API will be used by React to 1) find out if a user is authenticated, and 2) perform global logout.

package com.okta.developer.jugtours.web ; import org.springframework.http.HttpStatus ; import org.springframework.http.ResponseEntity ; import org.springframework.security.core.annotation.AuthenticationPrincipal ; import org.springframework.security.oauth2.client.registration.ClientRegistration ; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository ; import org.springframework.security.oauth2.core.oidc.OidcIdToken ; import org.springframework.security.oauth2.core.user.OAuth2User ; import org.springframework.web.bind.annotation.GetMapping ; import org.springframework.web.bind.annotation.PostMapping ; import org.springframework.web.bind.annotation.RestController ; import javax.servlet.http.HttpServletRequest ; import java.util.HashMap ; import java.util.Map ; @RestController public class UserController { private ClientRegistration registration ; public UserController ( ClientRegistrationRepository registrations ) { this . registration = registrations . findByRegistrationId ( “okta” ); } @GetMapping ( “/api/user” ) public ResponseEntity getUser ( @AuthenticationPrincipal OAuth2User user ) { if ( user == null ) { return new ResponseEntity <>( “” , HttpStatus . OK ); } else { return ResponseEntity . ok (). body ( user . getAttributes ()); } } @PostMapping ( “/api/logout” ) public ResponseEntity logout ( HttpServletRequest request , @AuthenticationPrincipal ( expression = “idToken” ) OidcIdToken idToken ) { // send logout URL to client so they can initiate logout String logoutUrl = this . registration . getProviderDetails () . getConfigurationMetadata (). get ( “end_session_endpoint” ). toString (); Map < String , String > logoutDetails = new HashMap <>(); logoutDetails . put ( “logoutUrl” , logoutUrl ); logoutDetails . put ( “idToken” , idToken . getTokenValue ()); request . getSession ( false ). invalidate (); return ResponseEntity . ok (). body ( logoutDetails ); } }

You’ll also want to add user information when creating groups so that you can filter by your JUG tour. Add a UserRepository.java in the same directory as GroupRepository.java .

package com.okta.developer.jugtours.model ; import org.springframework.data.jpa.repository.JpaRepository ; public interface UserRepository extends JpaRepository < User , String > { }

Add a new findAllByUserId(String id) method to GroupRepository.java .

List < Group > findAllByUserId ( String id );

Then inject UserRepository into GroupController.java and use it to create (or grab an existing user) when adding a new group. While you’re there, modify the groups() method to filter by user.

package com.okta.developer.jugtours.web ; import com.okta.developer.jugtours.model.Group ; import com.okta.developer.jugtours.model.GroupRepository ; import com.okta.developer.jugtours.model.User ; import com.okta.developer.jugtours.model.UserRepository ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; import org.springframework.http.HttpStatus ; import org.springframework.http.ResponseEntity ; import org.springframework.security.core.annotation.AuthenticationPrincipal ; import org.springframework.security.oauth2.core.user.OAuth2User ; import org.springframework.web.bind.annotation.* ; import javax.validation.Valid ; import java.net.URI ; import java.net.URISyntaxException ; import java.security.Principal ; import java.util.Collection ; import java.util.Map ; import java.util.Optional ; @RestController @RequestMapping ( “/api” ) class GroupController { private final Logger log = LoggerFactory . getLogger ( GroupController . class ); private GroupRepository groupRepository ; private UserRepository userRepository ; public GroupController ( GroupRepository groupRepository , UserRepository userRepository ) { this . groupRepository = groupRepository ; this . userRepository = userRepository ; } @GetMapping ( “/groups” ) Collection < Group > groups ( Principal principal ) { return groupRepository . findAllByUserId ( principal . getName ()); } @GetMapping ( “/group/{id}” ) ResponseEntity getGroup ( @PathVariable Long id ) { Optional < Group > group = groupRepository . findById ( id ); return group . map ( response -> ResponseEntity . ok (). body ( response )) . orElse ( new ResponseEntity <>( HttpStatus . NOT_FOUND )); } @PostMapping ( “/group” ) ResponseEntity < Group > createGroup ( @Valid @RequestBody Group group , @AuthenticationPrincipal OAuth2User principal ) throws URISyntaxException { log . info ( “Request to create group: {}” , group ); Map < String , Object > details = principal . getAttributes (); String userId = details . get ( “sub” ). toString (); // check to see if user already exists Optional < User > user = userRepository . findById ( userId ); group . setUser ( user . orElse ( new User ( userId , details . get ( “name” ). toString (), details . get ( “email” ). toString ()))); Group result = groupRepository . save ( group ); return ResponseEntity . created ( new URI ( “/api/group/” + result . getId ())) . body ( result ); } @PutMapping ( “/group/{id}” ) ResponseEntity < Group > updateGroup ( @Valid @RequestBody Group group ) { log . info ( “Request to update group: {}” , group ); Group result = groupRepository . save ( group ); return ResponseEntity . ok (). body ( result ); } @DeleteMapping ( “/group/{id}” ) public ResponseEntity deleteGroup ( @PathVariable Long id ) { log . info ( “Request to delete group: {}” , id ); groupRepository . deleteById ( id ); return ResponseEntity . ok (). build (); } }

To magnify the changes, they’re in the groups() and createGroup() methods. It’s pretty slick that Spring JPA will create the findAllByUserId() method/query for you and userRepository.findById() uses Java 8’s Optional.

@GetMapping ( “/groups” ) Collection < Group > groups ( Principal principal ) { return groupRepository . findAllByUserId ( principal . getName ()); } @PostMapping ( “/group” ) ResponseEntity < Group > createGroup ( @Valid @RequestBody Group group , @AuthenticationPrincipal OAuth2User principal ) throws URISyntaxException { log . info ( “Request to create group: {}” , group ); Map < String , Object > details = principal . getAttributes (); String userId = details . get ( “sub” ). toString (); // check to see if user already exists Optional < User > user = userRepository . findById ( userId ); group . setUser ( user . orElse ( new User ( userId , details . get ( “name” ). toString (), details . get ( “email” ). toString ()))); Group result = groupRepository . save ( group ); return ResponseEntity . created ( new URI ( “/api/group/” + result . getId ())) . body ( result ); }

Modify React to handle CSRF and be identity-aware

You’ll need to make a few changes to your React components to make them identity-aware. The first thing you’ll want to do is modify src/index.js to wrap everything in a CookieProvider . This component allows you to read the CSRF cookie and send it back as a header.

import { CookiesProvider } from ‘ react-cookie ‘ ; const root = ReactDOM . createRoot ( document . getElementById ( ‘ root ‘ )); root . render ( < React . StrictMode > < CookiesProvider > < App /> );

Modify app/src/Home.js to call /api/user to see if the user is logged in. If they’re not, show a Login button.

import React , { useEffect , useState } from ‘ react ‘ ; import ‘ ./App.css ‘ ; import AppNavbar from ‘ ./AppNavbar ‘ ; import { Link } from ‘ react-router-dom ‘ ; import { Button , Container } from ‘ reactstrap ‘ ; import { useCookies } from ‘ react-cookie ‘ ; const Home = () => { const [ authenticated , setAuthenticated ] = useState ( false ); const [ loading , setLoading ] = useState ( false ); const [ user , setUser ] = useState ( undefined ); const [ cookies ] = useCookies ([ ‘ XSRF-TOKEN ‘ ]); useEffect (() => { setLoading ( true ); fetch ( ‘ api/user ‘ , { credentials : ‘ include ‘ }) . then ( response => response . text ()) . then ( body => { if ( body === ” ) { setAuthenticated ( false ); } else { setUser ( JSON . parse ( body )); setAuthenticated ( true ); } setLoading ( false ); }); }, [ setAuthenticated , setLoading , setUser ]) const login = () => { let port = ( window . location . port ? ‘ : ‘ + window . location . port : ” ); if ( port === ‘ :3000 ‘ ) { port = ‘ :8080 ‘ ; } window . location . href = `// ${ window . location . hostname }${ port } /private` ; } const logout = () => { fetch ( ‘ /api/logout ‘ , { method : ‘ POST ‘ , credentials : ‘ include ‘ , headers : { ‘ X-XSRF-TOKEN ‘ : cookies [ ‘ XSRF-TOKEN ‘ ] } }) . then ( res => res . json ()) . then ( response => { window . location . href = ` ${ response . logoutUrl } ?id_token_hint= ${ response . idToken } ` + `&post_logout_redirect_uri= ${ window . location . origin } ` ; }); } const message = user ? < h2 > Welcome, { user . name } ! : < p > Please log in to manage your JUG Tour. ; const button = authenticated ? < div > < Button color = "link" >< Link to = "/groups" > Manage JUG Tour < br /> < Button color = "link" onClick = { logout } > Logout : < Button color = "primary" onClick = { login } > Login ; if ( loading ) { return < p > Loading… ; } return ( < div > < AppNavbar /> < Container fluid > { message } { button } ); } export default Home ;

There are some things you should be aware of in this component:

useCookies() is used for access to cookies. Then you can fetch a cookie with cookies[‘XSRF-TOKEN’] . When using fetch() , you need to include {credentials: ‘include’} to transfer cookies. You will get a 403 Forbidden if you do not include this option. The CSRF cookie from Spring Security has a different name than the header you need to send back. The cookie name is XSRF-TOKEN , while the header name is X-XSRF-TOKEN .

Update app/src/GroupList.js to have similar changes. The good news is you don’t need to make any changes to the render() method.

import { useCookies } from ‘ react-cookie ‘ ; const GroupList = () => { … const [ cookies ] = useCookies ([ ‘ XSRF-TOKEN ‘ ]); … const remove = async ( id ) => { await fetch ( `/api/group/ ${ id } ` , { method : ‘ DELETE ‘ , headers : { ‘ X-XSRF-TOKEN ‘ : cookies [ ‘ XSRF-TOKEN ‘ ], ‘ Accept ‘ : ‘ application/json ‘ , ‘ Content-Type ‘ : ‘ application/json ‘ }, credentials : ‘ include ‘ }). then (() => { let updatedGroups = [… groups ]. filter ( i => i . id !== id ); setGroups ( updatedGroups ); }); } … return (…) } export default GroupList ;

Update GroupEdit.js too.

import { useCookies } from ‘ react-cookie ‘ ; const GroupEdit = () => { … const [ cookies ] = useCookies ([ ‘ XSRF-TOKEN ‘ ]); … const handleSubmit = async ( event ) => { event . preventDefault (); await fetch ( `/api/group ${ group . id ? `/ ${ group . id } ` : ” } ` , { method : group . id ? ‘ PUT ‘ : ‘ POST ‘ , headers : { ‘ X-XSRF-TOKEN ‘ : cookies [ ‘ XSRF-TOKEN ‘ ], ‘ Accept ‘ : ‘ application/json ‘ , ‘ Content-Type ‘ : ‘ application/json ‘ }, body : JSON . stringify ( group ), credentials : ‘ include ‘ }); setGroup ( initialFormState ); navigate ( ‘ /groups ‘ ); } … return (…) } export default GroupEdit ;

After all these changes, you should be able to restart both Spring Boot and React and witness the glory of planning your very own JUG Tour!

Configure Maven to build and package React with Spring Boot

To build and package your React app with Maven, you can use the frontend-maven-plugin and Maven’s profiles to activate it. Add properties for versions and a section to your pom.xml .

1.12.1 v16.15.1 v8.6.0 dev true dev prod maven-resources-plugin copy-resources process-classes copy-resources ${basedir}/target/classes/static app/build com.github.eirslett frontend-maven-plugin ${frontend-maven-plugin.version} app install node install-node-and-npm ${node.version} ${npm.version} npm install npm generate-resources npm test test test test true npm build npm compile run build prod

While you’re at it, add the active profile setting to src/main/resources/application.properties :

spring.profiles.active = @spring.profiles.active@

After adding this, you should be able to run ./mvnw spring-boot:run -Pprod and see your app running on http://localhost:8080 .

Learn more about Spring Boot and React

I hope you’ve enjoyed this tutorial on how to do CRUD with React, Spring Boot, and Spring Security. You can see that Spring Security’s OIDC support is pretty robust, and doesn’t require a whole lot of configuration. Adding CSRF protection and packaging your Spring Boot + React app as a single artifact is pretty cool too!

You can find the example created in this tutorial on GitHub at https://github.com/oktadev/okta-spring-boot-react-crud-example.

We’ve written some other cool Spring Boot and React tutorials. Check them out if you’re interested.

If you have any questions, please don’t hesitate to leave a comment below or ask us on our Okta Developer Forums. Follow us on Twitter if you want to see more tutorials like this one!

React JS + Spring Boot REST API Example Tutorial

In this tutorial, we will create a simple “single page application” using React as frontend and spring boot as backend.

React is used to build user interfaces (UI) on the front end.

Spring boot is popular to develop RESTful web services and microservices.

Learn spring boot at https://www.javaguides.net/p/spring-boot-tutorial.html

If you want to use React Hooks in React App then check out React JS ( React Hooks) + Spring Boot Tutorial

As we know, React is a JavaScript-based library that does not have the ability to make HTTP requests; thus, we need to use third-party libraries to achieve this.

There are plenty of libraries available to make HTTP calls into React apps. A few of them are listed below.

Axios

Fetch

Superagent

React-axios

Use-http

React-request

We will use the Axios HTTP library to make HTTP Get REST API call in this example tutorial.

YouTube Video

5. Prerequisites

Basic familiarity with HTML & CSS

Basic knowledge of JavaScript and programming

Spring Boot Basics

ReactJS basics

Node.js and npm installed globally

What we will build?

We will build two projects:

sprintboot-backend (server) – To develop REST API react-frontend (client) – Consume REST API

Client-Server Architecture

1. Develop Spring Boot Backend Application

We will use Spring Data JPA to develop the repository layer and we use the H2 in-memory database to store the data.

1. Create a Spring Boot Application

There are many ways to create a Spring Boot application. You can refer to below articles to create a Spring Boot application.

2. Add maven dependencies

< project xmlns = " http://maven.apache.org/POM/4.0.0 " xmlns : xsi = " http://www.w3.org/2001/XMLSchema-instance " xsi:schemaLocation= " http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd " > < modelVersion >4.0.0 < parent > < groupId >org.springframework.boot < artifactId >spring-boot-starter-parent < version >2.3.0.RELEASE < relativePath /> < groupId >net.javaguides < artifactId >springboot-backend < version >0.0.1-SNAPSHOT < name >springboot-backend < description >Demo project for Spring Boot < properties > < java .version>1.8 < dependencies > < dependency > < groupId >org.springframework.boot < artifactId >spring-boot-starter-data-jpa < dependency > < groupId >org.springframework.boot < artifactId >spring-boot-starter-web < dependency > < groupId >com.h2database < artifactId >h2 < scope >runtime < dependency > < groupId >org.springframework.boot < artifactId >spring-boot-starter-test < scope >test < exclusions > < exclusion > < groupId >org.junit.vintage < artifactId >junit-vintage-engine < build > < plugins > < plugin > < groupId >org.springframework.boot < artifactId >spring-boot-maven-plugin

Create JPA Entity – User.java

Create a new package called model inside net.javaguides.springboot package and then create the User class inside the model package with the following contents –

package net.javaguides.springboot.model ; import javax.persistence.Column ; import javax.persistence.Entity ; import javax.persistence.GeneratedValue ; import javax.persistence.GenerationType ; import javax.persistence.Id ; import javax.persistence.Table ; @Entity @Table ( name = ” users ” ) public class User { @Id @GeneratedValue ( strategy = GenerationType . IDENTITY ) private long id; @Column ( name = ” first_name ” ) private String firstName; @Column ( name = ” last_name ” ) private String lastName; private String email; public User () { } public User ( String firstName , String lastName , String email ) { super (); this . firstName = firstName; this . lastName = lastName; this . email = email; } public long getId () { return id; } public void setId ( long id ) { this . id = id; } public String getFirstName () { return firstName; } public void setFirstName ( String firstName ) { this . firstName = firstName; } public String getLastName () { return lastName; } public void setLastName ( String lastName ) { this . lastName = lastName; } public String getEmail () { return email; } public void setEmail ( String email ) { this . email = email; } }

Create Spring Data JPA Repository – UserRepository.java

Create a new package called repository inside net.javaguides.springboot package and then create the following interface inside the repository package –

package net.javaguides.springboot.repository ; import org.springframework.data.jpa.repository.JpaRepository ; import org.springframework.stereotype.Repository ; import net.javaguides.springboot.model.User ; @Repository public interface UserRepository extends JpaRepository< User , Long > { }

Spring Controller with REST API – /api/users

Let’s create a UserController class and add the following code to it:

package net.javaguides.springboot.controller ; import java.util.List ; import org.springframework.beans.factory.annotation.Autowired ; import org.springframework.web.bind.annotation.CrossOrigin ; import org.springframework.web.bind.annotation.GetMapping ; import org.springframework.web.bind.annotation.RequestMapping ; import org.springframework.web.bind.annotation.RestController ; import net.javaguides.springboot.model.User ; import net.javaguides.springboot.repository.UserRepository ; @CrossOrigin ( origins = ” http://localhost:3000 ” ) @RestController @RequestMapping ( ” api/ ” ) public class UserController { @Autowired private UserRepository userRepository; @GetMapping ( ” users ” ) public List < User > getUsers () { return this . userRepository . findAll(); } }

Note that we have added the below line of code to avoid CORS issues:

@CrossOrigin(origins = “http://localhost:3000″)

Run Spring Boot Application and Test Rest API

Let’s insert a few records in the users table while application startup.

Let’s run this spring boot application from IDE -> Right-click -> Run As -> Java Application:

package net.javaguides.springboot ; import org.springframework.beans.factory.annotation.Autowired ; import org.springframework.boot.CommandLineRunner ; import org.springframework.boot.SpringApplication ; import org.springframework.boot.autoconfigure.SpringBootApplication ; import net.javaguides.springboot.model.User ; import net.javaguides.springboot.repository.UserRepository ; @SpringBootApplication public class SpringbootBackendApplication implements CommandLineRunner { public static void main ( String [] args ) { SpringApplication . run( SpringbootBackendApplication . class, args); } @Autowired private UserRepository userRepository; @Override public void run ( String … args ) throws Exception { this . userRepository . save( new User ( ” Ramesh ” , ” Fadatare ” , ” [email protected] ” )); this . userRepository . save( new User ( ” Tom ” , ” Cruise ” , ” [email protected] ” )); this . userRepository . save( new User ( ” Tony ” , ” Stark ” , ” [email protected] ” )); } }

Hit this ” http://localhost:8080/api/users ” link in a browser will popular list of users as JSON:

[{ ” id ” : 1 , ” firstName ” : ” Ramesh ” , ” lastName ” : ” Fadatare ” , ” email ” : ” [email protected] ” },{ ” id ” : 2 , ” firstName ” : ” Tom ” , ” lastName ” : ” Cruise ” , ” email ” : ” [email protected] ” },{ ” id ” : 3 , ” firstName ” : ” Tony ” , ” lastName ” : ” Stark ” , ” email ” : ” [email protected] ” }]

Build React JS Frontend Application

Let’s go ahead and create a React application to consume /api/users REST API.

1 – Create a React UI with Create React App

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

To create a new app, you may choose one of the following methods:

Using npx

npx create-react-app react-frontend

Using npm

npm init react-app react-frontend

npm init is available in npm 6+

Using Yarn

yarn create react-app react-frontend

Running any of these commands will create a directory called react-frontend inside the current folder. Inside that directory, it will generate the initial project structure and install the transitive dependencies:

react-frontend ├── README.md ├── node_modules ├── package.json ├── .gitignore ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js

Let’s explore important files and folders of the react project.

For the project to build, these files must exist with exact filenames:

public/index.html is the page template;

is the page template; src/index.js is the JavaScript entry point.

You can delete or rename the other files Let’s quickly explore the project structure.

package.json – The package.json file contains all the required dependencies for our React JS project. Most importantly, you can check the current version of React that you are using. It has all the scripts to start, build, and eject our React app.

public folder – The public folder contains index.html . As react is used to build a single page application, we have this single HTML file to render all our components. Basically, it’s an HTML template. It has a div element with id as root and all our components are rendered in this div with index.html as a single page for the complete react app.

src folder- In this folder, we have all the global javascript and CSS files. All the different components that we will be building, sit here.

index.js – This is the top renderer of your react app.

node_modules – All the packages installed by NPM or Yarn will reside inside the node_modules folder.

App.js – The App.js file contains the definition of our App component which actually gets rendered in the browser and this is the root component.

2 – Adding Bootstrap in React Using NPM Open a new terminal window, navigate to your project’s folder, and run the following command: $ npm install bootstrap –save After installing the bootstrap package, you will need to import it in your React app entry file. Open the src/index.js file and add the following code: import ‘bootstrap/dist/css/bootstrap.min.css’ ;

src/index.js Here is the complete code for the index.js file: import React from ‘react’ ; import ReactDOM from ‘react-dom’ ; import ‘./index.css’ ; import App from ‘./App’ ; import * as serviceWorker from ‘./serviceWorker’ ; import ‘bootstrap/dist/css/bootstrap.min.css’ ; ReactDOM . render ( < React . StrictMode > < App / > < / React . StrictMode > , document . getElementById ( ‘root’ ) ) ; // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker . unregister ( ) ;

3. React Service Component – REST API Call For our API calls, we will be using Axios . Below is the npm command to install Axios . npm add axios

Below is the UserService.js service implementation to make our HTTP REST call via Axios.

Our backend User endpoint is available at http://localhost:8080/api/users

import axios from ‘axios’ const USERS_REST_API_URL = ‘http://localhost:8080/api/users’ ; class UserService { getUsers ( ) { return axios . get ( USERS_REST_API_URL ) ; } } export default new UserService ( ) ;

Make sure that you create an object of UserService class export it as:

export default new UserService ( ) ;

4. Develop a React Component

Components are the building blocks of our whole react app. They are like functions that accept inputs in terms of props, state, and outputs a UI that is rendered in the browser. They are reusable and composable.

React components can be either a function component or a class component. In this example, we are going to use the class component.

Let’s create a UserComponent.js file and add the following code to it.

import React from ‘react’ ; import UserService from ‘../services/UserService’ ; class UserComponent extends React . Component { constructor ( props ) { super ( props ) this . state = { users : [ ] } } componentDidMount ( ) { UserService . getUsers ( ) . then ( ( response ) => { this . setState ( { users : response . data } ) } ) ; } render ( ) { return ( < div > < h1 className = "text-center" > Users List < / h1 > < table className = "table table-striped" > < thead > < tr > < td > User Id < / td > < td > User First Name < / td > < td > User Last Name < / td > < td > User Email Id < / td > < / tr > < / thead > < tbody > { this . state . users . map ( user => < tr key = { user . id } > < td > { user . id } < / td > < td > { user . firstName } < / td > < td > { user . lastName } < / td > < td > { user . email } < / td > < / tr > ) } < / tbody > < / table > < / div > ) } } export default UserComponent

Let’s understand the above code step by step.

constructor() – The constructor () is invoked before the component is mounted. In the constructor, we have declared our state variables and bind the different methods so that they are accessible from the state inside of the render() method.

componentDidMount() – The componentDidMount() is called as soon as the component is mounted and ready.

render() – The render() method is the most used lifecycle method. The render() method actually outputs HTML to the DOM.

We are using the map operator to loop over our user list and create the view like:

{ this . state . users . map ( user => < tr key = { user . id } > < td > { user . id } < / td > < td > { user . firstName } < / td > < td > { user . lastName } < / td > < td > { user . email } < / td > < / tr > ) }

5. App.js

In the previous step, we have created UserComponent so let’s go ahead add UserComponent to the App component:

import React from ‘react’ ; import logo from ‘./logo.svg’ ; import ‘./App.css’ ; import UserComponent from ‘./components/UserComponent’ ; function App ( ) { return ( < div className = "App" > < UserComponent / > < / div > ) ; } export default App ;

6. Run React App

Use the below command to start the project:

npm start

Use yarn to start the project:

yarn start

Runs the app in development mode. Open http://localhost:3000 to view it in the browser.

Conclusion

In this tutorial, we have created a simple “single page application” using React as frontend and spring boot as backend. We have also seen how to integrate React frontend application with spring boot backend using Axios HTTP library.

How to fetch data from an API in ReactJS ?

How to fetch data from an API in ReactJS ?

ReactJS: ReactJS is a declarative, efficient, and flexible JavaScript library for building user interfaces. It’s ‘V’ in MVC. ReactJS is an open-source, component-based front-end library responsible only for the view layer of the application. It is maintained by Facebook.

API: API is an abbreviation for Application Programming Interface which is a collection of communication protocols and subroutines used by various programs to communicate between them. A programmer can make use of various API tools to make its program easier and simpler. Also, an API facilitates the programmers with an efficient way to develop their software programs.

Approach: In this article, we will know how we fetch the data from API (Application Programming Interface). For the data, we have used the API endpoint from http://jsonplaceholder.typicode.com/users we have created the component in App.js and styling the component in App.css. From the API we have target “id”, “name”, “username”, “email” and fetch the data from API endpoints. Below is the stepwise implementation of how we fetch the data from an API in react. We will use the fetch function to get the data from the API.

Step by step implementation to fetch data from an api in react.

Step 1: Create React Project npm create-react-app MY-APP

Step 2: Change your directory and enter your main folder charting as cd MY-APP

Step 3: API endpoint https://jsonplaceholder.typicode.com/users

Step 4: Write code in App.js to fetch data from API and we are using fetch function.

Project Structure: It will look the following.

Example:

App.js

import React from “react” ; import ‘./App.css’ ; class App extends React.Component { constructor(props) { super (props); this .state = { items: [], DataisLoaded: false }; } componentDidMount() { fetch( “https://jsonplaceholder.typicode.com/users” ) .then((res) => res.json()) .then((json) => { this .setState({ items: json, DataisLoaded: true }); }) } render() { const { DataisLoaded, items } = this .state; if (!DataisLoaded) return

Pleses wait some time….

; return (

Fetch data from an api in react

{ items.map((item) => (

    User_Name: { item.username }, Full_Name: { item.name }, User_Email: { item.email }

)) }

); } } export default App;

Write code in App.css for styling the app.js file.

App.css

.App { text-align : center ; color : Green; } .App-header { background-color : #282c34 ; min-height : 100 vh; display : flex; flex- direction : column; align-items: center ; justify- content : center ; font-size : calc( 10px + 2 vmin); color : white ; } .App-link { color : #61dafb ; } @keyframes App-logo-spin { from { transform: rotate( 0 deg); } to { transform: rotate( 360 deg); } }

Step to run the application: Open the terminal and type the following command.

npm start

Output: Open the browser and our project is shown in the URL http://localhost:3000/

Using React Spring for animation: Context and examples

Animations in React

Animations have evolved to very complicated UI element manipulations. They are used to increase interactivity on web pages and to give users an engaging experience while using websites. Developers are constantly looking to find better ways to implement animations without causing a major performance bottleneck.

Animation effects are applied on the UI thread which is usually called frequently, as a result, adding certain animations/animation libraries could have negative impacts on your site. This is why we have chosen to discuss React Spring as a tool you should consider using to animate your React apps. Find out more with examples in the video below.

React Spring

React Spring is a spring-physics based animation library that powers most UI related animation in React. It is a bridge on the two existing React animation libraries; React Motion and Animated. Given the performance considerations of animation libraries, React Spring is the best of both worlds. It inherits animated powerful interpolations and performance while maintaining react-motion’s ease of use.

Having understood what React Spring is, and what it offers, let’s take a look at how we can use it to build seamless animations in React applications. We’ll explore its features to better understand its strengths.

Prerequisites

Before we go any further, this article assumes the following:

Node.js ≥v6 is installed on your machine

npm is installed on your machine

You have a basic understanding of React.js

You have a basic understanding of React hooks

React Spring example setup

The best way to add React Spring to your application will be via the package managers. Simply open a terminal window on your project’s root directory and run the installation command below:

npm install react-spring #OR yarn add react-spring

This makes React Spring widely available in your application for later use.

With the introduction of hooks in React, you can add state to functional components. React Spring takes this up a notch by providing a hook based API which allows you to define and convert data that you would generally pass as props to animated data.

To better demonstrate some of the features of React Spring, let’s take a closer look at the available hooks in the React-spring module. There are five major hooks available in React Spring at the moment:

useSpring — A single spring, moves data from a to b

— A single spring, moves data from a to b useSprings — Multiple springs mainly for lists, where each spring moves data from a -> b

— Multiple springs mainly for lists, where each spring moves data from a -> b useTrail — Multiple springs with a single data set, one spring follows or trails behind the other

— Multiple springs with a single data set, one spring follows or trails behind the other useTransition — For mount/unmount transitions (lists where items are added/removed/updated)

— For mount/unmount transitions (lists where items are added/removed/updated) useChain — To queue or chain multiple animations together

For each of these hooks, there are several animation effects you can implement, it’s limitless and goes as far as your imagination will take you. We’ll look at some use cases for useSpring , useSprings and useTrail to demonstrate how you can implement them in your React applications.

Using useSpring in React

useSpring is one of the simplest React Spring hooks. It turns defined values into animated values. It does this in two ways, either by overwriting the existing props with a different set of props on component re-render or by passing an updater function that returns a different set of props that is then used to update the props using set .

Import it into the needed component like so, since we’ll be using the hooks API in this explanation:

import {useSpring, animated} from ‘react-spring’

Here are the two methods for using the useSpring hooks:

1) Overwriting existing props

const props = useSpring({opacity: toggle ? 1 : 0})

Here, if you re-render the component with changed props, the animation will update automatically.

2) Passing an updater function

In this case, there is no re-rendering. This method is mostly applied for fast occurring updates. It also has an optional argument ( stop ) to stop animation.

const [props, set, stop] = useSpring(() => ({opacity: 1})) // Update spring with new props set({opacity: toggle ? 1 : 0}) // Stop animation stop()

Since we are animating, we would be moving data from one state to another. Spring naturally comes with two props: from and to to show the initial position and the end position of the animation.

We will discuss this further when explaining the render-in-props API. Now, to get a feel of how the useSpring hook API works, here’s a small demo that shows a simple animated greeting card for a landing page:

On CodeSandbox:

From the demo above we can see that the first few lines of code express the initial state and the final position of the box we are trying to animate:

const contentProps = useSpring({ opacity: greetingStatus ? 1 : 0, marginTop: greetingStatus ? 0 : -500 });

In this example, the content slides in from the top of the page down to the center. The value of -500 marginTop is to set the position off-screen , then define an opacity of 0 as our values for the from prop. We do this to achieve a certain appearance of the box. These values are assigned to contentProps which we then pass as props to animated.div like so:

Hey there ! React Spring is awesome.

Creating multiple strings with useSprings

useSprings is just like useSpring ; the only difference is that it is used to create multiple springs, each with its own config. It is mostly used for lists, where each spring moves data from an initial state to a final state. This also provides us with two options on how to implement. Since we are working with multiple values, this method works in two forms.

Overwrite values to change the animation

Here, the animation is updated to each element by triggering a props change. It is simply achieved like this:

const springs = useSprings(number, items.map(item => ({ opacity: item.opacity }))

From the snippet above, we can see that the list items are mapped to have the useSpring method act on each element. That way, we can trigger the animation to happen on each element.

Pass a function that returns values, and update using “set”

You will get an updater function back. It will not cause the component to render like an overwrite would (still the animation will execute, of course). Handling updates like this is most useful for fast-occurring updates.

const [springs, set, stop] = useSprings(number, index => ({opacity: 1})) // Update springs with new props set(index => ({opacity: 0})) // Stop all springs stop()

How do we use this? Imagine we have a list of people and we wanted a user to know exactly which person is being selected, a cool way to bring more life to this would be to explore this demonstration by Paul Henschel.

On CodeSandbox:

Single config example with useTrail

useTrial enables us to create multiple springs with a single configuration. It has almost the same configuration as useSpring with a variation in the implementation. It animates the first item of a list of elements while the rest of the elements form a natural trail and follow their previous sibling:

return trail.map(props => )

It takes a list of items of any type and their keys. The latter defaults to item => item , however, if your items are self-sufficient as a key, it’ll often be good enough.

On CodeSandbox:

const config = { mass: 5, tension: 2000, friction: 200 };

The above line in the demo configures the common API of spring to set the default values of the parameters.

const trail = useTrail(items.length, { config, opacity: toggle ? 1 : 0, x: toggle ? 0 : 20, height: toggle ? 80 : 0, from: { opacity: 0, x: 20, height: 0 } });

The above snippet uses the listed props to set the initial and final conditions of the elements using the ternary operators to indicate the switch.

Render-props API

This method of implementing React Spring in projects was used in class components which was the default mode before React Hooks were introduced in React v16.8. For the sake of inclusiveness, let’s also explore it to accommodate developers on the older version of React. With this method, the importation into projects is a bit different.

Spring class component example

The class component implementation of animating a single element using React Spring would use spring as opposed to useSpring . As a result, we would import it into projects like so:

import {Spring} from ‘react-spring/renderprops’

As we mentioned earlier, Spring/useSpring makes use of two props from and to to show the initial position and the end position of the animation like so:

{props =>

hello

}

Trail class component example

In this case, we are dealing with the class component equivalent of useTrail and it is imported as:

import {Trail} from ‘react-spring/renderprops’

The working principle remains the same however, the mode of transformation becomes:

item.key} from={{transform: ‘translate3d(0,-40px,0)’}} to={{transform: ‘translate3d(0,0px,0)’}}> {item => props => {item.text}}

We can notice new props being used in the example above. They behave like keys that are being used to specify what item the animation is being carried out on. You can find more examples of props being accepted by trial in the docs examples.

The performance advantage of React Spring

The main advantage of React Spring over other animation libraries is its ability to apply animations without relying on React to render updates frame by frame. This advantage is usually noticed when dealing with nested routes or charts. For more information on the implementation of specific performance boosts, check out the official documentation.

Conclusion

In this article, we have analyzed some use cases using React Spring’s Hooks API and also explored the class component equivalents. Seeing the performance advantage and simple syntax of React Spring, I would strongly recommend using this in your projects as smooth animations help in ensuring awesome user experiences.

Full visibility into production React apps Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting with metrics like client CPU load, client memory usage, and more. The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores. Modernize how you debug your React apps — start monitoring for free.

키워드에 대한 정보 react spring api

다음은 Bing에서 react spring api 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 React JS + Spring Boot REST API Example Tutorial

  • spring boot
  • react
  • reactjs
  • spring mvc
  • java
  • java guides

React #JS #+ #Spring #Boot #REST #API #Example #Tutorial


YouTube에서 react spring api 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 React JS + Spring Boot REST API Example Tutorial | react spring api, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

Leave a Comment