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:
– ReactReduxHttpClient
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 ServerSpring 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:
Source Code
– SpringBootMySQL-server– ReactReduxHttpClient
By grokonez | May 3, 2018
I like your post.
ReplyDeleteComputer News
Latest Technology News
Tech News India
This comment has been removed by the author.
ReplyDeletethanks for tips at SynergisticIT offer the best Full Stack course training in california
ReplyDeleteexcellent blog!
ReplyDeletespring boot certification course
spring boot online training india
spring boot online training hyderabad
Spring Boot + React Redux And Mysql Crud Example ~ It Blog >>>>> Download Now
ReplyDelete>>>>> Download Full
Spring Boot + React Redux And Mysql Crud Example ~ It Blog >>>>> Download LINK
>>>>> Download Now
Spring Boot + React Redux And Mysql Crud Example ~ It Blog >>>>> Download Full
>>>>> Download LINK
Spring Boot + React Redux And Mysql Crud Example ~ It Blog >>>>> Download Now
ReplyDelete>>>>> Download Full
Spring Boot + React Redux And Mysql Crud Example ~ It Blog >>>>> Download LINK
>>>>> Download Now
Spring Boot + React Redux And Mysql Crud Example ~ It Blog >>>>> Download Full
>>>>> Download LINK 9R
ReplyDeleteMobil onay
mobil ödeme bozdurma
NFT NASİL ALINIR
ankara evden eve nakliyat
TRAFİK SİGORTASI
dedektor
web sitesi kurma
aşk kitapları
Good content. You write beautiful things.
ReplyDeletevbet
korsan taksi
sportsbet
vbet
mrbahis
hacklink
mrbahis
taksi
sportsbet
Good text Write good content success. Thank you
ReplyDeletebetpark
betmatik
kibris bahis siteleri
slot siteleri
kralbet
poker siteleri
bonus veren siteler
mobil ödeme bahis
dijital kartvizit
ReplyDeletereferans kimliği nedir
binance referans kodu
referans kimliği nedir
bitcoin nasıl alınır
resimli magnet
30ZT
hatay
ReplyDeletekars
mardin
samsun
urfa
C8K63D
https://saglamproxy.com
ReplyDeletemetin2 proxy
proxy satın al
knight online proxy
mobil proxy satın al
KYEOBH
arnavutköy
ReplyDeleteartvin
avcılar
aydın
bağcılar
3G06X4
kaş
ReplyDeletebeykoz
bahçeşehir
pendik
tekirdağ
WPPC
شركة تسليك مجاري بالاحساء Wp8GDQ3vR4
ReplyDeleteشركة عزل اسطح LfZQfHoVMd
ReplyDelete