Sunday 16 July 2023

React CRUD application with JWT Authentication and file upload or download + Spring Boot API

In this tutorial, we’re gonna build a React CRUD (Create, Read, Update, Delete) Application with JWT Authentication, File upload/ download, and consume CRUD Restful APIs developed by Spring boot.

  • JWT Authentication Flow for User Signup & User Login.
  • Project Structure for React JWT Authentication (without Redux) with LocalStorage, React Router, Axios, react-bootstrap, react-hook-form.
  • Creating React Components with Form Validation.
  • Dynamic Navigation Bar in React App.

Let's start with creating a React App using create-react-app CLI.

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

Using npx
npx create-react-app react-appname

Using npm
npm init react-app react-appname












Install some npm packages:

npm install bootstrap reactstrap
npm install react-bootstrap bootstrap
npm install reactstrap react react-dom
npm install axios
npm install react-router-dom
npm install react-hook-form











------------------------------packege.json--------------------------------
{
  "name": "react-hooks-jwt-auth",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "axios": "^0.26.1",
    "bootstrap": "^4.6.2",
    "react": "^17.0.2",
    "react-bootstrap": "^2.8.0",
    "react-dom": "^17.0.2",
    "react-hook-form": "^7.45.1",
    "react-router-dom": "^6.14.1",
    "react-scripts": "4.0.3",
    "react-validation": "^3.0.7",
    "reactstrap": "^9.2.0",
    "validator": "^13.0.0"
  },
  "scripts": {
    "start": "react-scripts --openssl-legacy-provider start",
    "build": "react-scripts --openssl-legacy-provider build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}


------------------------------app.js--------------------------------

import React, { useState, useEffect } from "react";
import { Routes, Route, Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";

import AuthService from "./services/auth.service";

import Login from "./components/Login";
import Register from "./components/Register";
import Home from "./components/Home";
import Profile from "./components/Profile";
import BoardUser from "./components/BoardUser";
import BoardModerator from "./components/BoardModerator";
import BoardAdmin from "./components/BoardAdmin";
import FormSubmit from "./components/FormSubmit";
import EventBus from "./common/EventBus";
import FormDataFetch from "./components/FormDataFetch";
import FormDtailView from "./components/FormDetailView";
import FormDetailEdit from "./components/FormDetailEdit";

const App = () => {
  const [showModeratorBoard, setShowModeratorBoard] = useState(false);
  const [showAdminBoard, setShowAdminBoard] = useState(false);
  const [currentUser, setCurrentUser] = useState(undefined);

  useEffect(() => {
    const user = AuthService.getCurrentUser();

    if (user) {
      setCurrentUser(user);
      setShowModeratorBoard(user.roles.includes("ROLE_MODERATOR"));
      setShowAdminBoard(user.roles.includes("ROLE_ADMIN"));
    }

    EventBus.on("logout", () => {
      logOut();
    });

    return () => {
      EventBus.remove("logout");
    };
  }, []);

  const logOut = () => {
    AuthService.logout();
    setShowModeratorBoard(false);
    setShowAdminBoard(false);
    setCurrentUser(undefined);
  };

  return (
    <div>
      <nav className="navbar navbar-expand navbar-dark bg-dark">
        <Link to={"/"} className="navbar-brand">
          Ramsis Code
        </Link>
        <div className="navbar-nav mr-auto">
          <li className="nav-item">
            <Link to={"/home"} className="nav-link">
              Home
            </Link>
          </li>

          {showModeratorBoard && (
            <li className="nav-item">
              <Link to={"/mod"} className="nav-link">
                Moderator Board
              </Link>
            </li>
          )}

          {showAdminBoard && (
            <li className="nav-item">
              <Link to={"/admin"} className="nav-link">
                Admin Board
              </Link>
            </li>
          )}

          {currentUser && (
            <li className="nav-item">
              <Link to={"/user"} className="nav-link">
                User
              </Link>
            </li>
          )}

        {currentUser && (
           <li className="nav-item">
              <Link to={"/formDataFetch"} className="nav-link">
                Record Fetch
              </Link>
            </li>
        )}    
        </div>

        {currentUser ? (
          <div className="navbar-nav ml-auto">
            <li className="nav-item">
              <Link to={"/profile"} className="nav-link">
                {currentUser.username}
              </Link>
            </li>
            <li className="nav-item">
              <a href="/login" className="nav-link" onClick={logOut}>
                LogOut
              </a>
            </li>
          </div>
        ) : (
          <div className="navbar-nav ml-auto">
            <li className="nav-item">
              <Link to={"/login"} className="nav-link">
                Login
              </Link>
            </li>

            <li className="nav-item">
              <Link to={"/register"} className="nav-link">
                Sign Up
              </Link>
            </li>
          </div>
        )}
      </nav>

      <div className="container mt-3">
        <Routes>
          <Route path="/" element={<Home/>} />
          <Route path="/home" element={<Home/>} />
          <Route path="/login" element={<Login/>} />
          <Route path="/register" element={<Register/>} />
          <Route path="/profile" element={<Profile/>} />
          <Route path="/user" element={<BoardUser/>} />
          <Route path="/mod" element={<BoardModerator/>} />
          <Route path="/admin" element={<BoardAdmin/>} />
          <Route path="/formDataFetch" element={<FormDataFetch/>} />
          <Route path="/formFill" element={<FormSubmit/>} />
          <Route path="/formFill" element={<FormSubmit/>} />
          <Route path="/formDetailView/:id" element={<FormDtailView/>} />
          <Route path="/formDetailEdit/:id" element={<FormDetailEdit/>} />
        </Routes>
      </div>

    </div>
  );
};

export default App;


-------------------------------------auth.service.js----------------------------------------

import axios from "axios";

const API_URL = "http://localhost:8080/api/auth/";

const register = (username, email, password) => {
  return axios.post(API_URL + "signup", {
    username,
    email,
    password,
  });
};

const login = (username, password) => {
  alert(username +" "+password);
  return axios
    .post(API_URL + "signin", {
      username,
      password,
    })
    .then((response) => {
      if (response.data.accessToken) {
        localStorage.setItem("user", JSON.stringify(response.data));
        localStorage.setItem("facilityId", "NHA12039");
        localStorage.setItem("facilityName", "Kalesh Hospital Delhi");
        localStorage.setItem("Role", "Hospital");

      }

      return response.data;
    });
};

const logout = () => {
  localStorage.removeItem("user");
};

const getCurrentUser = () => {
  return JSON.parse(localStorage.getItem("user"));
};

const AuthService = {
  register,
  login,
  logout,
  getCurrentUser,
};

export default AuthService;



------------------------------------------ auth-header.js---------------------------------------

export default function authHeader() {
  const user = JSON.parse(localStorage.getItem('user'));

  if (user && user.accessToken) {
    return { Authorization: 'Bearer ' + user.accessToken }; // for Spring Boot back-end
    // return { 'x-access-token': user.accessToken };       // for Node.js Express back-end
  } else {
    return {};
  }
}


-------------------------------------user.service.js--------------------------------------

import axios from "axios";
import authHeader from "./auth-header";

const API_URL = "http://localhost:8080/api/test/";
const APP_URL = "http://localhost:8080/api/app/";

const getPublicContent = () => {
  return axios.get(API_URL + "all");
};

const getUserBoard = () => {
  return axios.get(API_URL + "user", { headers: authHeader() });
};

const getModeratorBoard = () => {
  return axios.get(API_URL + "mod", { headers: authHeader() });
};

const getAdminBoard = () => {
  return axios.get(API_URL + "admin", { headers: authHeader() });
};

const getFormData = () => {
  return axios.get(API_URL + "formData", { headers: authHeader() });
};

const getFormDataList = () => {
  return axios.get(APP_URL + "getFormData", { headers: authHeader() });
};

const getFormDataById = (id) => {
  return axios.get(APP_URL + "getFormDataById/"+id, { headers: authHeader() });
};

const saveForm = (userObject) =>{
 //console.log(userObject.name);
  const user = JSON.parse(localStorage.getItem('user'));
  return axios.post(APP_URL +"formInsert",userObject,
  { headers:{
    "Content-Type": "multipart/form-data",
    "Authorization" : 'Bearer '+user.accessToken,
  }}
  );
}

const updateForm = (userObject,id) =>{
   const user = JSON.parse(localStorage.getItem('user'));
   return axios.put(APP_URL +"formUpdate/"+id,userObject,
   { headers:{
     "Content-Type": "multipart/form-data",
     "Authorization" : 'Bearer '+user.accessToken,
   }}
   );
 }

 const deleteUser = (id) => {
  return axios.delete(APP_URL + "deleteUser/"+id, { headers: authHeader() });
};

const getFile = () => {
  return axios.get(APP_URL + "files", { headers: authHeader() });
};

const UserService = {
  getPublicContent,
  getUserBoard,
  getModeratorBoard,
  getAdminBoard,
  getFormData,
  saveForm,
  getFormDataList,
  getFormDataById,
  updateForm,
  deleteUser,
  getFile,
  APP_URL,
 
};

export default UserService;



--------------------------------- FormDetailFetch.js------------------------------

import { useState, useEffect} from "react";
import { Routes, Route, Link } from "react-router-dom";
import FormSubmit from "./FormSubmit";
import UserService from "../services/user.service";
import Table from 'react-bootstrap/Table';
import EventBus from "../common/EventBus";
import FormDtailView from "./FormDetailView";
import FormDetailEdit from "./FormDetailEdit";

const FormDataFetch = () => {
const [users, setUsers] = useState([]);
const [message,setMessage] = useState("");

   const userList = () =>{
    UserService.getFormDataList().then(
        (response) => {
          console.log(response.data);
          setUsers(response.data);
        },
        (error) => {
          if (error.response===401 || error.response.data.status === 401) {
            EventBus.dispatch("logout");
          }
        }
      );
   }  


   useEffect(()=> {
    userList();
   },[])

   const deleteUser = async(id) => {
        const response = await UserService.deleteUser(id)
        userList();
        setMessage(response.data.message+" user id :"+id);
   }

   return<>
    <Link to={"/formFill"} className="badge badge-primary">
        Form Registration
    </Link>  
    <div className="container">
    <h5>User List</h5>
    {message &&(<div className="alert alert-success">
     {message}
    </div>)}
     <Table striped bordered hover>
        <thead>
           <th>Id</th>
           <th>Name</th>
           <th>Email</th>
           <th>Department</th>
           <th>Phone</th>
           <th>City</th>
           <th>Download</th>
           <th>Image</th>
           <th>View</th>
           <th>Edit</th>
           <th>Delete</th>
        </thead>
        <tbody>
        {
        users.map((user,index)=>(
               
            <tr>  
               <td>{index+1}</td>                
               <td>{user.name}</td>
               <td>{user.email}</td>
               <td>{user.department}</td>
               <td>{user.phone}</td>
               <td>{user.city}</td>
               <td>  
               <a href={user.url}>{user.fileName}</a>
              </td>
              <td><img src={user.url} width="60" height="40" alt={user.fileName}></img></td>
               <td><Link className="btn btn-primary" to={"/formDetailView/"+user.id}>view</Link></td>
               <td><Link className="btn btn-primary" to={"/formDetailEdit/"+user.id}>Edit</Link></td>
               <td><Link className="btn btn-danger" onClick={()=>deleteUser(user.id)}>Delete</Link></td>
            </tr>
        ))
        }
        </tbody>
     </Table>


    <div className="container mt-3">
        <Routes>
         <Route path="/formFill" element={<FormSubmit/>} />
         <Route path="/formDetailView/:id" element={<FormDtailView/>} />
         <Route path="/formDetailEdit/:id" element={<FormDetailEdit/>} />
        </Routes>
    </div>
    </div>  
    </>
}
export default FormDataFetch;


-----------------------------------FormSubmit.js-------------------------------

import React, { useState, useEffect } from "react";
import UserService from "../services/user.service";
import EventBus from "../common/EventBus";
import Form from 'react-bootstrap/Form';


const FormSubmit = () => {
  const [content, setContent] = useState("");

  useEffect(() => {
    UserService.getFormData().then(
      (response) => {
        setContent(response.data);
      },
      (error) => {
        const _content =
          (error.response &&
            error.response.data &&
            error.response.data.message) ||
          error.message ||
          error.toString();

        setContent(_content);

        if (error.response && error.response.status === 401) {
          EventBus.dispatch("logout");
        }
      }
    );
  }, []);

  const onChangePicture = e => {
    console.log('selectFile: ', selectFile);
    setSelectFile(e.target.files[0]);
};

  const [name,setName] = useState("");
  const [email,setEmail] = useState("");
  const [department,setDepartment] = useState("");
  const [phone,setPhone] = useState("");
  const [city,setCity] = useState("");
  const [selectFile, setSelectFile] = useState("");
  const [msg, setMessage] = useState("");
  const [msgName, setMsgName] = useState("");
  const [msgEmail, setMsgEmail] = useState("");
  const [msgDept, setMsgDept] = useState("");
  const [msgCity, setMsgCity] = useState("");
  const [msgPhone, setMsgPhone] = useState("");
  const [msgFile, setMsgFile] = useState("");
 
  const validate = () => {
    let returnError=false;
    const regexEmail = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i;

    if(name===''){
      setMsgName("Name is Required.");
      returnError=true;
    }else{
      setMsgName('');
      returnError=false;
    }

    if(email===''){
      setMsgEmail("Email is Required.");
      returnError=true;
    }else if(!regexEmail.test(email)){
      setMsgEmail("Invalid Email.");
      returnError=true;
    } else{
      setMsgEmail('');
      returnError=false;
    }
   

    if(department===''){
      setMsgDept("Department is Required.");
      returnError=true;
    }else{
      setMsgDept('');
      returnError=false;
    }

    if(phone===''){
      setMsgPhone("Phone is Required.");
      returnError=true;
    }else{
      setMsgPhone('');
      returnError=false;
    }
   
    if(city===''){
      setMsgCity("City is Required.");
      returnError=true;
    }else{
      setMsgCity('');
      returnError=false;
    }

    if(selectFile===''){
      setMsgFile("File is Required.");
      returnError=true;
    }else{
      setMsgFile('');
      returnError=false;
    }

    return returnError;

  }
 
  const submitForm = (e) =>{
    e.preventDefault();

    const returnError = validate();  

    if(returnError===false){

          const userObject = new FormData();
          userObject.append("name",name);
          userObject.append("email",email);
          userObject.append("department",department);
          userObject.append("phone",phone);
          userObject.append("city",city);
          userObject.append("selectFile",selectFile);

          UserService.saveForm(userObject)
       
          .then((response)=>{
            if(response.status===200){
             // setMessage(response.data.message);
              alert(response.data.message);
              setName('');
              setEmail('');
              setDepartment('');
              setPhone('');
              setCity('');
              setSelectFile('');
            }
          })
          .catch((error)=>{
            console.log(error);
          setMessage(error.response.data.message);
          })
        }
   }


  return (
    <div className="container">
     <div className="row"></div>
      <header className="jumbotron">
       
    <Form onSubmit={submitForm}>
      <h5>{content}</h5>
        {msg &&(<div className="alert alert-success">
         {msg}
       </div>)}
      <div className="form-group">  
      <label className="form-label">Name</label>
      <input type="text" placeholder="name" value={name} onChange={(e)=> setName(e.target.value)} />
      {msgName && <p style={{color: "red"}}>{msgName}</p>}
     </div>
     <div className="form-group">
     <label className="form-label">Email address</label>
      <input type="email" placeholder="name@example.com"  value={email}
onChange={(e)=> setEmail(e.target.value)} />
      {msgEmail && <p style={{color: "red"}}>{msgEmail}</p>}
    </div>
    <div className="form-group">
     <label className="form-label">Department</label>
      <input type="text" placeholder="Department"  value={department}
onChange={(e)=> setDepartment(e.target.value)} />
      {msgDept && <p style={{color: "red"}}>{msgDept}</p>}
    </div>
    <div className="form-group">
    <label className="form-label">Phone</label>
      <input type="text"  placeholder="phone" value={phone} onChange={(e)=> setPhone(e.target.value)} />
      {msgPhone && <p style={{color: "red"}}>{msgPhone}</p>}
     </div>
     <div className="form-group">
     <label className="form-label">City</label>
      <input type="text" placeholder="city"   value={city} onChange={(e)=> setCity(e.target.value)} />
      {msgCity && <p style={{color: "red"}}>{msgCity}</p>}
     </div>

     <div className="form-group">
     <label className="form-label">Upload</label>
      <input type="file"  onChange={onChangePicture} />
      {msgFile && <p style={{color: "red"}}>{msgFile}</p>}
     </div>
     <div className="form-group">
      <button className="btn btn-primary">Submit</button>
      </div>
     </Form>  
     </header>
    </div>
  );
};

export default FormSubmit;



---------------------------------FormDetailEdit.js------------------------------------

import React, { useState, useEffect } from "react";
import UserService from "../services/user.service";
import Form from 'react-bootstrap/Form';
import { useParams } from "react-router-dom";
import { useForm } from "react-hook-form";

const FormDetailEdit = () =>{

  const {register,handleSubmit,formState: { errors },} = useForm();

    const {id} = useParams();
    const [name,setName] = useState("");
    const [email,setEmail] = useState("");
    const [department,setDepartment] = useState("");
    const [phone,setPhone] = useState("");
    const [city,setCity] = useState("");
    const [message,setMessage] = useState("");
    const [selectFile, setSelectFile] = useState("");
   const loadUserListById= ()=>{

        UserService.getFormDataById(id).then(
            (response) => {
            const {name,department,email,phone,city} = response.data;
            setName(name);
            setEmail(email);
            setDepartment(department);
            setPhone(phone);
            setCity(city);
            console.log(email);
            },
            (error) => {
                setMessage(error.response.data.message);
            }
          );

    }

    useEffect(()=> {
        loadUserListById();
    },[])


    const updateForm = (e) =>{
       // e.preventDefault();
     
        const userObject = new FormData();
        userObject.append("name",name);
        userObject.append("email",email);
        userObject.append("department",department);
        userObject.append("phone",phone);
        userObject.append("city",city);
        userObject.append("selectFile",selectFile);

      UserService.updateForm(userObject,id)
    .then((response)=>{
       if(response.status===200){
        setMessage(response.data.message);
       }
    })
    .catch((error)=>{
      console.log(error);
     setMessage(error.response.data.message);
    })
  }

  const onChangePicture = e => {
    console.log('selectFile: ', selectFile);
    setSelectFile(e.target.files[0]);
};

    return <>
    <div className="container">
     <div className="row"></div>
      <header className="jumbotron">
        <h5>User Edit</h5>
        {message &&(<div className="alert alert-success">
         {message}
       </div>)}
      <Form onSubmit={handleSubmit (updateForm)}>
      <div className="form-group">  
       <label className="form-label">Name</label>
        <input  {...register("name", { required: "Name is required" })}
placeholder="name" value={name} type="text" onChange={(e)=> setName(e.target.value)} />
        {errors.name?.message && <p style={{color: "red"}}>{errors.name?.message}  </p>}
      </div>
     
      <div className="form-group">  
        <label className="form-label">Email address</label>
        <input  {...register("email", { required: "Email is required" ,
 pattern:{value: /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i, message: "Invalid email." }})}
type="text" placeholder="name@example.com" value={email} onChange={(e)=>
setEmail(e.target.value)} />
        {errors.email?.message && <p style={{color: "red"}}>{errors.email?.message}</p>}
      </div>

      <div className="form-group">  
        <label className="form-label">Department</label>
        <input {...register("department", { required: "Department is required" })}
type="text" placeholder="Department" value={department} onChange={(e)=> setDepartment(e.target.value)} />
        {errors.department?.message && <p style={{color: "red"}}>{errors.department?.message}  </p>}
      </div>

      <div className="form-group">  
        <label className="form-label">Phone</label>
        <input {...register("phone", { required: "Phone is required" })}  
type="text" placeholder="phone" value={phone} onChange={(e)=> setPhone(e.target.value)} />
        {errors.phone?.message && <p style={{color: "red"}}>{errors.phone?.message}  </p>}
      </div>

      <div className="form-group">  
        <label className="form-label">City</label>
        <input {...register("city", { required: "City is required" })}  type="text"
placeholder="city" value={city} onChange={(e)=> setCity(e.target.value)} />
        {errors.city?.message && <p style={{color: "red"}}>{errors.city?.message}  </p>}
      </div>

      <div className="form-group">  
        <label className="form-label">Upload</label>
        <input {...register("selectFile", { required: "File is required" })}
type="file" onChange={onChangePicture} />
        {errors.selectFile?.message && <p style={{color: "red"}}>
{errors.selectFile?.message}  </p>}
      </div>
      <div className="form-group">  
      <button className="btn btn-primary">Update</button>
      </div>
     </Form>  
      </header>
    </div>
    </>
}

export default FormDetailEdit;

--------------------------------FormDetailView.js-------------------------------


import { useState, useEffect} from "react";
import { useParams } from "react-router-dom";
import UserService from "../services/user.service";
import EventBus from "../common/EventBus";

const FormDtailView = () => {

    const {id} = useParams();
    const [name,setName] = useState("");
    const [email,setEmail] = useState("");
    const [department,setDepartment] = useState("");
    const [phone,setPhone] = useState("");
    const [city,setCity] = useState("");
    const [message,setMessage] = useState("");
    const fileUrl = UserService.APP_URL+"files/"+id;
     const loadUserListById= ()=>{
        UserService.getFormDataById(id).then(
            (response) => {
            const {name,department,email,phone,city} = response.data;
            setName(name);
            setEmail(email);
            setDepartment(department);
            setPhone(phone);
            setCity(city);
            console.log(email);
            },
            (error) => {
                setMessage(error.response.data.message);
                if (error.response===401 || error.response.data.status === 401) {
                    EventBus.dispatch("logout");
                  }
            }
          );

    }

    useEffect(()=> {
        loadUserListById();
    },[])

    return <>
    <h2>Detail View</h2>
     <h5>{message}</h5>
    Name : {name} <br/>
    Email :{email} <br/>
    Department :{department} <br/>
    Phone :{phone} <br/>
    City :{city} <br/><br/>
    <div>
    <img src={fileUrl} height="200" width="200"></img>
    </div>
    </>
}
export default FormDtailView;


------------------------------Register.js-------------------------------

import React, { useState, useRef } from "react";
import Form from "react-validation/build/form";
import Input from "react-validation/build/input";
import CheckButton from "react-validation/build/button";
import { isEmail } from "validator";

import AuthService from "../services/auth.service";

const required = (value) => {
  if (!value) {
    return (
      <div className="alert alert-danger" role="alert">
        This field is required!
      </div>
    );
  }
};

const validEmail = (value) => {
  if (!isEmail(value)) {
    return (
      <div className="alert alert-danger" role="alert">
        This is not a valid email.
      </div>
    );
  }
};

const vusername = (value) => {
  if (value.length < 3 || value.length > 20) {
    return (
      <div className="alert alert-danger" role="alert">
        The username must be between 3 and 20 characters.
      </div>
    );
  }
};

const vpassword = (value) => {
  if (value.length < 6 || value.length > 40) {
    return (
      <div className="alert alert-danger" role="alert">
        The password must be between 6 and 40 characters.
      </div>
    );
  }
};

const Register = () => {
  const form = useRef();
  const checkBtn = useRef();

  const [username, setUsername] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [successful, setSuccessful] = useState(false);
  const [message, setMessage] = useState("");

  const onChangeUsername = (e) => {
    const username = e.target.value;
    setUsername(username);
  };

  const onChangeEmail = (e) => {
    const email = e.target.value;
    setEmail(email);
  };

  const onChangePassword = (e) => {
    const password = e.target.value;
    setPassword(password);
  };

  const handleRegister = (e) => {
    e.preventDefault();

    setMessage("");
    setSuccessful(false);

    form.current.validateAll();

    if (checkBtn.current.context._errors.length === 0) {
      AuthService.register(username, email, password).then(
        (response) => {
          setMessage(response.data.message);
          setSuccessful(true);
        },
        (error) => {
          const resMessage =
            (error.response &&
              error.response.data &&
              error.response.data.message) ||
            error.message ||
            error.toString();

          setMessage(resMessage);
          setSuccessful(false);
        }
      );
    }
  };

  return (
    <div className="col-md-12">
      <div className="card card-container">
        <img
          src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
          alt="profile-img"
          className="profile-img-card"
        />

        <Form onSubmit={handleRegister} ref={form}>
          {!successful && (
            <div>
              <div className="form-group">
                <label htmlFor="username">Username</label>
                <Input
                  type="text"
                  className="form-control"
                  name="username"
                  value={username}
                  onChange={onChangeUsername}
                  validations={[required, vusername]}
                />
              </div>

              <div className="form-group">
                <label htmlFor="email">Email</label>
                <Input
                  type="text"
                  className="form-control"
                  name="email"
                  value={email}
                  onChange={onChangeEmail}
                  validations={[required, validEmail]}
                />
              </div>

              <div className="form-group">
                <label htmlFor="password">Password</label>
                <Input
                  type="password"
                  className="form-control"
                  name="password"
                  value={password}
                  onChange={onChangePassword}
                  validations={[required, vpassword]}
                />
              </div>

              <div className="form-group">
                <button className="btn btn-primary btn-block">Sign Up</button>
              </div>
            </div>
          )}

          {message && (
            <div className="form-group">
              <div
                className={
                  successful ? "alert alert-success" : "alert alert-danger"
                }
                role="alert"
              >
                {message}
              </div>
            </div>
          )}
          <CheckButton style={{ display: "none" }} ref={checkBtn} />
        </Form>
      </div>
    </div>
  );
};

export default Register;



Spring Boot API






Download Code