This article will build React Redux Http Client & Spring Boot Server example that uses Spring Data JPA to interact with MySQL database and React as a front-end technology to make request and receive response.
Technologies
– Java 1.8
– Maven 3.3.9
– Spring Tool Suite 3.9.0.RELEASE
– Spring Boot 2.0.1.RELEASE
– Webpack 4.4.1
– React 16.3.0
– Redux 3.7.2
– React Redux 5.0.7
– axios 0.18.0
– MySQL 5.7.16

Spring Data JPA with MySQL example:
How to use Spring JPA with MySQL | Spring Boot
2. React Redux Client
– AppRouter is for routing.
– actions, reducers and store contains Redux elements.
– components folder includes React Components with react-redux
– axios configures base URL for HTTP client. We use axios methods as async side-effects inside actions/books.js.
1.1 Dependency
pom.xml
model/Book.java
package com.javasampleapproach.spring.mysql.model;
import java.io.Serializable;
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 = "book")
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "title")
private String title;
@Column(name = "author")
private String author;
@Column(name = "description")
private String description;
@Column(name = "published")
private int published;
protected Book() {
}
..
}
1.3 Repository
repo/BookRepository.java
package com.javasampleapproach.spring.mysql.repo;
import org.springframework.data.repository.CrudRepository;
import com.javasampleapproach.spring.mysql.model.Book;
public interface BookRepository extends CrudRepository<Book, Long>{
}
1.4 REST Controller
controller/BookController.java
package com.javasampleapproach.spring.mysql.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.javasampleapproach.spring.mysql.model.Book;
import com.javasampleapproach.spring.mysql.repo.BookRepository;
@CrossOrigin(origins = "http://localhost:8081")
@RestController
@RequestMapping("/api")
public class BookController {
@Autowired
BookRepository bookRepository;
@GetMapping("/books")
public List<book> getAllBooks() {
System.out.println("Get all Books...");
List<book> list = new ArrayList<>();
Iterable<book> customers = bookRepository.findAll();
customers.forEach(list::add);
return list;
}
@PostMapping("/books/create")
public Book createBook(@Valid @RequestBody Book book) {
System.out.println("Create Book: " + book.getTitle() + "...");
return bookRepository.save(book);
}
@GetMapping("/books/{id}")
public ResponseEntity<book> getBook(@PathVariable("id") Long id) {
System.out.println("Get Book by id...");
Optional<book> bookData = bookRepository.findById(id);
if (bookData.isPresent()) {
return new ResponseEntity<>(bookData.get(), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PutMapping("/books/{id}")
public ResponseEntity<book> updateBook(@PathVariable("id") Long id,
@RequestBody Book book) {
System.out.println("Update Book with ID = " + id + "...");
Optional<book> bookData = bookRepository.findById(id);
if (bookData.isPresent()) {
Book savedBook = bookData.get();
savedBook.setTitle(book.getTitle());
savedBook.setAuthor(book.getAuthor());
savedBook.setDescription(book.getDescription());
savedBook.setPublished(book.getPublished());
Book updatedBook = bookRepository.save(savedBook);
return new ResponseEntity<>(updatedBook, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@DeleteMapping("/books/{id}")
public ResponseEntity<string> deleteBook(@PathVariable("id") Long id) {
System.out.println("Delete Book with ID = " + id + "...");
try {
bookRepository.deleteById(id);
} catch (Exception e) {
return new ResponseEntity<>("Fail to delete!",
HttpStatus.EXPECTATION_FAILED);
}
return new ResponseEntity<>("Book has been deleted!", HttpStatus.OK);
}
}
1.5 Configuration for Spring Datasource & JPA properties
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.generate-ddl=true
2. React Redux Client
2.1 Dependency
package.json
..
.babelrc
{
"presets": [
"env",
"react"
],
"plugins": [
"transform-object-rest-spread"
]
}
Run cmd:
2.2 Configure base URL
axios/axios.js
2.3 Redux Action
actions/books.js
import axios from '../axios/axios';
const _addBook = (book) => ({
type: 'ADD_BOOK',
book
});
export const addBook = (bookData = {
title: '',
description: '',
author: '',
published: 0
}) => {
return (dispatch) => {
const book = {
title: bookData.title,
description: bookData.description,
author: bookData.author,
published: bookData.published
};
return axios.post('books/create', book).then(result => {
dispatch(_addBook(result.data));
});
};
};
const _removeBook = ({ id } = {}) => ({
type: 'REMOVE_BOOK',
id
});
export const removeBook = ({ id } = {}) => {
return (dispatch) => {
return axios.delete(`books/${id}`).then(() => {
dispatch(_removeBook({ id }));
})
}
};
const _editBook = (id, updates) => ({
type: 'EDIT_BOOK',
id,
updates
});
export const editBook = (id, updates) => {
return (dispatch) => {
return axios.put(`books/${id}`, updates).then(() => {
dispatch(_editBook(id, updates));
});
}
};
const _getBooks = (books) => ({
type: 'GET_BOOKs',
books
});
export const getBooks = () => {
return (dispatch) => {
return axios.get('books').then(result => {
const books = [];
result.data.forEach(item => {
books.push(item);
});
dispatch(_getBooks(books));
});
};
};
2.4 Redux Reducer
reducers/books.js
store/store.js
import { createStore, applyMiddleware } from "redux";
import books from '../reducers/books';
import thunk from 'redux-thunk';
export default () => {
return createStore(books, applyMiddleware(thunk));
};
2.6 React Components
components/Book.js
import React from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { removeBook } from '../actions/books';
const Book = ({ id, title, description, author, published, dispatch }) => (
<div>
<link to="{`/book/${id}`}">
<h4>{title} ({published})</h4>
<p>Author: {author}</p>
{description && <p>{description}</p>}
<button onclick="{()" ==""> {
dispatch(removeBook({ id }));
}}>Remove</button>
</div>
);
export default connect()(Book);
components/DashBoard.js
import React from 'react';
import BookList from './BookList';
const DashBoard = () => (
<div classname="container__list">
<booklist>
</booklist></div>
);
export default DashBoard;
components/BookList.js
import React from 'react';
import { connect } from 'react-redux';
import Book from './Book';
const BookList = (props) => (
<div>
Book List:
<ul>
{props.books.map(book => {
return (
<li key="{book.id}">
<book {...book}="">
</book></li>
);
})}
</ul>
</div>
);
const mapStateToProps = (state) => {
return {
books: state
};
}
export default connect(mapStateToProps)(BookList);
components/AddBook.js
import React from 'react';
import BookForm from './BookForm';
import { connect } from 'react-redux';
import { addBook } from '../actions/books';
const AddBook = (props) => (
<div>
<h3>Set Book information:</h3>
<bookform onsubmitbook="{(book)" ==""> {
props.dispatch(addBook(book));
props.history.push('/');
}}
/>
</bookform></div>
);
export default connect()(AddBook);
components/EditBook.js
import React from 'react';
import BookForm from './BookForm';
import { connect } from 'react-redux';
import { editBook } from '../actions/books';
const EditBook = (props) => (
<div classname="container__box">
<bookform book="{props.book}" onsubmitbook="{(book)" ==""> {
props.dispatch(editBook(props.book.id, book));
props.history.push('/');
}}
/>
</bookform></div>
);
const mapStateToProps = (state, props) => {
return {
book: state.find((book) =>
book.id === props.match.params.id)
};
};
export default connect(mapStateToProps)(EditBook);
components/BookForm.js
import React from 'react';
export default class BookForm extends React.Component {
constructor(props) {
super(props);
this.onTitleChange = this.onTitleChange.bind(this);
this.onAuthorChange = this.onAuthorChange.bind(this);
this.onDescriptionChange = this.onDescriptionChange.bind(this);
this.onPublishedChange = this.onPublishedChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
title: props.book ? props.book.title : '',
author: props.book ? props.book.author : '',
description: props.book ? props.book.description : '',
published: props.book ? props.book.published : 0,
error: ''
};
}
onTitleChange(e) {
const title = e.target.value;
this.setState(() => ({ title: title }));
}
onAuthorChange(e) {
const author = e.target.value;
this.setState(() => ({ author: author }));
}
onDescriptionChange(e) {
const description = e.target.value;
this.setState(() => ({ description: description }));
}
onPublishedChange(e) {
const published = parseInt(e.target.value);
this.setState(() => ({ published: published }));
}
onSubmit(e) {
e.preventDefault();
if (!this.state.title || !this.state.author || !this.state.published) {
this.setState(() => ({
error: 'Please set title & author & published!' }));
} else {
this.setState(() => ({ error: '' }));
this.props.onSubmitBook(
{
title: this.state.title,
author: this.state.author,
description: this.state.description,
published: this.state.published
}
);
}
}
render() {
return (
<div>
{this.state.error && <p className='error'>{this.state.error}</p>}
<form onSubmit={this.onSubmit} className='add-book-form'>
<input type="text" placeholder="title" autoFocus
value={this.state.title}
onChange={this.onTitleChange} />
<br />
<input type="text" placeholder="author"
value={this.state.author}
onChange={this.onAuthorChange} />
<br />
<textarea placeholder="description"
value={this.state.description}
onChange={this.onDescriptionChange} />
<br />
<input type="number" placeholder="published"
value={this.state.published}
onChange={this.onPublishedChange} />
<br />
<button>Add Book</button>
</form>
</div>
);
}
}
2.7 React Router
routers/AppRouter.js
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Header from '../components/Header';
import DashBoard from '../components/DashBoard';
import AddBook from '../components/AddBook';
import EditBook from '../components/EditBook';
import NotFound from '../components/NotFound';
const AppRouter = () => (
<BrowserRouter>
<div className='container'>
<Header />
<Switch>
<Route path="/" component={DashBoard} exact={true} />
<Route path="/add" component={AddBook} />
<Route path="/book/:id" component={EditBook} />
<Route component={NotFound} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
components/Header.js
import React from 'react';
import { NavLink } from 'react-router-dom';
const Header = () => (
<header>
<h2>Java Sample Approach</h2>
<h4>Book Mangement Application</h4>
<div className='header__nav'>
<NavLink to='/' activeClassName='activeNav'
exact={true}>Dashboard</NavLink>
<NavLink to='/add' activeClassName='activeNav'>Add Book</NavLink>
</div>
</header>
);
export default Header;
2.8 Render App
app.js
import React from 'react';
import ReactDOM from 'react-dom';
import AppRouter from './routers/AppRouter';
import getAppStore from './store/store';
import { getBooks } from './actions/books';
import './styles/styles.scss';
import { Provider } from 'react-redux';
const store = getAppStore();
const template = (
<Provider store={store}>
<AppRouter />
</Provider>
);
store.dispatch(getBooks()).then(() => {
ReactDOM.render(template, document.getElementById('app'));
});
– Run the React App with command:
– Open browser for url
Add Book:

Show Books:


Technologies
– Java 1.8
– Maven 3.3.9
– Spring Tool Suite 3.9.0.RELEASE
– Spring Boot 2.0.1.RELEASE
– Webpack 4.4.1
– React 16.3.0
– Redux 3.7.2
– React Redux 5.0.7
– axios 0.18.0
– MySQL 5.7.16
Overview
1. Spring Boot Server
Spring Data JPA with MySQL example:
How to use Spring JPA with MySQL | Spring Boot
2. React Redux Client

For more details about:
– Redux: A simple practical Redux example
– Middleware: Middleware with Redux Thunk
– Connecting React with Redux: How to connect React with Redux – react-redux example

– Class Book corresponds to document in books collection.
– BookRepository is an interface extends CrudRepository, will be autowired in BookController for implementing repository methods and finder methods.
– BookController is a REST Controller which has request mapping methods for RESTful requests such as:
– Configuration for Spring Data JPA properties in application.properties.
– Dependencies for Spring Boot and Spring Data JPA in pom.xml.

For more details about:
– Redux: A simple practical Redux example
– Middleware: Middleware with Redux Thunk
– Connecting React with Redux: How to connect React with Redux – react-redux example
Practice
Project Structure
1. Spring Boot Server
– Class Book corresponds to document in books collection.
– BookRepository is an interface extends CrudRepository, will be autowired in BookController for implementing repository methods and finder methods.
– BookController is a REST Controller which has request mapping methods for RESTful requests such as:
getAll, create, update, delete Books.– Configuration for Spring Data JPA properties in application.properties.
– Dependencies for Spring Boot and Spring Data JPA in pom.xml.
2. React Redux Client
– AppRouter is for routing.
– actions, reducers and store contains Redux elements.
– components folder includes React Components with react-redux
connect() function.– axios configures base URL for HTTP client. We use axios methods as async side-effects inside actions/books.js.
How to do
1. Spring Boot Server1.1 Dependency
pom.xml
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-jpa</artifactid>
</dependency>
<dependency>
<groupid>mysql</groupid>
<artifactid>mysql-connector-java</artifactid>
<scope>runtime</scope>
</dependency>
1.2 Book – Data Modelmodel/Book.java
package com.javasampleapproach.spring.mysql.model;
import java.io.Serializable;
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 = "book")
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "title")
private String title;
@Column(name = "author")
private String author;
@Column(name = "description")
private String description;
@Column(name = "published")
private int published;
protected Book() {
}
..
}
1.3 Repository
repo/BookRepository.java
package com.javasampleapproach.spring.mysql.repo;
import org.springframework.data.repository.CrudRepository;
import com.javasampleapproach.spring.mysql.model.Book;
public interface BookRepository extends CrudRepository<Book, Long>{
}
1.4 REST Controller
controller/BookController.java
package com.javasampleapproach.spring.mysql.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.javasampleapproach.spring.mysql.model.Book;
import com.javasampleapproach.spring.mysql.repo.BookRepository;
@CrossOrigin(origins = "http://localhost:8081")
@RestController
@RequestMapping("/api")
public class BookController {
@Autowired
BookRepository bookRepository;
@GetMapping("/books")
public List<book> getAllBooks() {
System.out.println("Get all Books...");
List<book> list = new ArrayList<>();
Iterable<book> customers = bookRepository.findAll();
customers.forEach(list::add);
return list;
}
@PostMapping("/books/create")
public Book createBook(@Valid @RequestBody Book book) {
System.out.println("Create Book: " + book.getTitle() + "...");
return bookRepository.save(book);
}
@GetMapping("/books/{id}")
public ResponseEntity<book> getBook(@PathVariable("id") Long id) {
System.out.println("Get Book by id...");
Optional<book> bookData = bookRepository.findById(id);
if (bookData.isPresent()) {
return new ResponseEntity<>(bookData.get(), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@PutMapping("/books/{id}")
public ResponseEntity<book> updateBook(@PathVariable("id") Long id,
@RequestBody Book book) {
System.out.println("Update Book with ID = " + id + "...");
Optional<book> bookData = bookRepository.findById(id);
if (bookData.isPresent()) {
Book savedBook = bookData.get();
savedBook.setTitle(book.getTitle());
savedBook.setAuthor(book.getAuthor());
savedBook.setDescription(book.getDescription());
savedBook.setPublished(book.getPublished());
Book updatedBook = bookRepository.save(savedBook);
return new ResponseEntity<>(updatedBook, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@DeleteMapping("/books/{id}")
public ResponseEntity<string> deleteBook(@PathVariable("id") Long id) {
System.out.println("Delete Book with ID = " + id + "...");
try {
bookRepository.deleteById(id);
} catch (Exception e) {
return new ResponseEntity<>("Fail to delete!",
HttpStatus.EXPECTATION_FAILED);
}
return new ResponseEntity<>("Book has been deleted!", HttpStatus.OK);
}
}
1.5 Configuration for Spring Datasource & JPA properties
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.generate-ddl=true
2. React Redux Client
2.1 Dependency
package.json
..
.babelrc
{
"presets": [
"env",
"react"
],
"plugins": [
"transform-object-rest-spread"
]
}
Run cmd:
yarn install.2.2 Configure base URL
axios/axios.js
import axios from 'axios'; export default axios.create({ baseURL: 'http://localhost:8080/api' });
|
2.3 Redux Action
actions/books.js
import axios from '../axios/axios';
const _addBook = (book) => ({
type: 'ADD_BOOK',
book
});
export const addBook = (bookData = {
title: '',
description: '',
author: '',
published: 0
}) => {
return (dispatch) => {
const book = {
title: bookData.title,
description: bookData.description,
author: bookData.author,
published: bookData.published
};
return axios.post('books/create', book).then(result => {
dispatch(_addBook(result.data));
});
};
};
const _removeBook = ({ id } = {}) => ({
type: 'REMOVE_BOOK',
id
});
export const removeBook = ({ id } = {}) => {
return (dispatch) => {
return axios.delete(`books/${id}`).then(() => {
dispatch(_removeBook({ id }));
})
}
};
const _editBook = (id, updates) => ({
type: 'EDIT_BOOK',
id,
updates
});
export const editBook = (id, updates) => {
return (dispatch) => {
return axios.put(`books/${id}`, updates).then(() => {
dispatch(_editBook(id, updates));
});
}
};
const _getBooks = (books) => ({
type: 'GET_BOOKs',
books
});
export const getBooks = () => {
return (dispatch) => {
return axios.get('books').then(result => {
const books = [];
result.data.forEach(item => {
books.push(item);
});
dispatch(_getBooks(books));
});
};
};
2.4 Redux Reducer
reducers/books.js
const booksReducerDefaultState = [];
export default (state = booksReducerDefaultState, action) => {
switch (action.type) {
case 'ADD_BOOK':
return [
...state,
action.book
];
case 'REMOVE_BOOK':
return state.filter(({ id }) => id !== action.id);
case 'EDIT_BOOK':
return state.map((book) => {
if (book.id === action.id) {
return {
...book,
...action.updates
};
} else {
return book;
}
});
case 'GET_BOOKs':
return action.books;
default:
return state;
}
};
2.5 Redux Storestore/store.js
import { createStore, applyMiddleware } from "redux";
import books from '../reducers/books';
import thunk from 'redux-thunk';
export default () => {
return createStore(books, applyMiddleware(thunk));
};
2.6 React Components
components/Book.js
import React from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { removeBook } from '../actions/books';
const Book = ({ id, title, description, author, published, dispatch }) => (
<div>
<link to="{`/book/${id}`}">
<h4>{title} ({published})</h4>
<p>Author: {author}</p>
{description && <p>{description}</p>}
<button onclick="{()" ==""> {
dispatch(removeBook({ id }));
}}>Remove</button>
</div>
);
export default connect()(Book);
components/DashBoard.js
import React from 'react';
import BookList from './BookList';
const DashBoard = () => (
<div classname="container__list">
<booklist>
</booklist></div>
);
export default DashBoard;
components/BookList.js
import React from 'react';
import { connect } from 'react-redux';
import Book from './Book';
const BookList = (props) => (
<div>
Book List:
<ul>
{props.books.map(book => {
return (
<li key="{book.id}">
<book {...book}="">
</book></li>
);
})}
</ul>
</div>
);
const mapStateToProps = (state) => {
return {
books: state
};
}
export default connect(mapStateToProps)(BookList);
components/AddBook.js
import React from 'react';
import BookForm from './BookForm';
import { connect } from 'react-redux';
import { addBook } from '../actions/books';
const AddBook = (props) => (
<div>
<h3>Set Book information:</h3>
<bookform onsubmitbook="{(book)" ==""> {
props.dispatch(addBook(book));
props.history.push('/');
}}
/>
</bookform></div>
);
export default connect()(AddBook);
components/EditBook.js
import React from 'react';
import BookForm from './BookForm';
import { connect } from 'react-redux';
import { editBook } from '../actions/books';
const EditBook = (props) => (
<div classname="container__box">
<bookform book="{props.book}" onsubmitbook="{(book)" ==""> {
props.dispatch(editBook(props.book.id, book));
props.history.push('/');
}}
/>
</bookform></div>
);
const mapStateToProps = (state, props) => {
return {
book: state.find((book) =>
book.id === props.match.params.id)
};
};
export default connect(mapStateToProps)(EditBook);
components/BookForm.js
import React from 'react';
export default class BookForm extends React.Component {
constructor(props) {
super(props);
this.onTitleChange = this.onTitleChange.bind(this);
this.onAuthorChange = this.onAuthorChange.bind(this);
this.onDescriptionChange = this.onDescriptionChange.bind(this);
this.onPublishedChange = this.onPublishedChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
title: props.book ? props.book.title : '',
author: props.book ? props.book.author : '',
description: props.book ? props.book.description : '',
published: props.book ? props.book.published : 0,
error: ''
};
}
onTitleChange(e) {
const title = e.target.value;
this.setState(() => ({ title: title }));
}
onAuthorChange(e) {
const author = e.target.value;
this.setState(() => ({ author: author }));
}
onDescriptionChange(e) {
const description = e.target.value;
this.setState(() => ({ description: description }));
}
onPublishedChange(e) {
const published = parseInt(e.target.value);
this.setState(() => ({ published: published }));
}
onSubmit(e) {
e.preventDefault();
if (!this.state.title || !this.state.author || !this.state.published) {
this.setState(() => ({
error: 'Please set title & author & published!' }));
} else {
this.setState(() => ({ error: '' }));
this.props.onSubmitBook(
{
title: this.state.title,
author: this.state.author,
description: this.state.description,
published: this.state.published
}
);
}
}
render() {
return (
<div>
{this.state.error && <p className='error'>{this.state.error}</p>}
<form onSubmit={this.onSubmit} className='add-book-form'>
<input type="text" placeholder="title" autoFocus
value={this.state.title}
onChange={this.onTitleChange} />
<br />
<input type="text" placeholder="author"
value={this.state.author}
onChange={this.onAuthorChange} />
<br />
<textarea placeholder="description"
value={this.state.description}
onChange={this.onDescriptionChange} />
<br />
<input type="number" placeholder="published"
value={this.state.published}
onChange={this.onPublishedChange} />
<br />
<button>Add Book</button>
</form>
</div>
);
}
}
2.7 React Router
routers/AppRouter.js
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Header from '../components/Header';
import DashBoard from '../components/DashBoard';
import AddBook from '../components/AddBook';
import EditBook from '../components/EditBook';
import NotFound from '../components/NotFound';
const AppRouter = () => (
<BrowserRouter>
<div className='container'>
<Header />
<Switch>
<Route path="/" component={DashBoard} exact={true} />
<Route path="/add" component={AddBook} />
<Route path="/book/:id" component={EditBook} />
<Route component={NotFound} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
components/Header.js
import React from 'react';
import { NavLink } from 'react-router-dom';
const Header = () => (
<header>
<h2>Java Sample Approach</h2>
<h4>Book Mangement Application</h4>
<div className='header__nav'>
<NavLink to='/' activeClassName='activeNav'
exact={true}>Dashboard</NavLink>
<NavLink to='/add' activeClassName='activeNav'>Add Book</NavLink>
</div>
</header>
);
export default Header;
2.8 Render App
app.js
import React from 'react';
import ReactDOM from 'react-dom';
import AppRouter from './routers/AppRouter';
import getAppStore from './store/store';
import { getBooks } from './actions/books';
import './styles/styles.scss';
import { Provider } from 'react-redux';
const store = getAppStore();
const template = (
<Provider store={store}>
<AppRouter />
</Provider>
);
store.dispatch(getBooks()).then(() => {
ReactDOM.render(template, document.getElementById('app'));
});
Run & Check Result
– Build and Run Spring Boot project with commandlines:mvn clean install and mvn spring-boot:run.– Run the React App with command:
yarn run dev-server.– Open browser for url
http://localhost:8081/:Add Book:

Show Books:


Code
By grokonez | May 3, 2018

thanks for tips at SynergisticIT offer the best Full Stack course training in california
Trả lờiXóa