React, Node Express, Mysql registration form stuck - mysql

I'm learning how to connect my front end to a database using middleware and trying to clone a waiver/registration form for a project my buddy gave me.
I can manually input data from the code editor to Mysql database but once I try to link it to the front end I get nothing, I'm completely stumped, can't really find any updated documentation on Node express syntax and mysql.
Here is my server and database code:
const express = require("express");
const app = express();
const mysql = require("mysql");
const bodyParser = require("body-parser");
const cors = require("cors");
const db = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "cloneDataBase",
});
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/api/get", (req, res) => {
const sqlGet = "SELECT * FROM customer_registration";
db.query(sqlGet, (error, result) => {
res.send(result);
});
});
app.post("/api/post", (req, res) => {
const { firstName, lastName, email, phone, nickName } = req.body;
const sqlInsert =
"INSERT INTO customer_registration (firstName, lastName, email, phone, nickName) VALUES (?,?,?,?,?)";
db.query(
sqlInsert,
[firstName, lastName, email, phone, nickName],
(error, result) => {
if (error) {
console.log(error);
}
}
);
});
heres my registration form.
import React, { useState } from "react";
import "./NewCustomer.css";
import { Link, useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import axios from "axios";
const initialState = {
firstName: "",
lastName: "",
email: "",
phone: "",
nickName: "",
};
export default function NewCustomer() {
const [state, setState] = useState(initialState);
const { firstName, lastName, email, phone, nickName } = state;
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefalut();
if (!firstName || !lastName || !email || !phone || !nickName) {
toast.error("Please Provide value into each input field");
} else {
axios
.post("http://localhost:3001/api/post", {
firstName,
lastName,
email,
phone,
nickName,
})
.then(() => {
setState({
firstName: "",
lastName: "",
email: "",
phone: "",
nickName: "",
});
})
.catch((err) => toast.error(err.response.data));
setTimeout(() => navigate.push("/"), 500);
}
};
// const handleInputChange = (e) => {
// const { name, value } = e.target;
// setState({ ...state, [name]: value });
// };
return (
<div className="container">
<div className="new-customer-reg">
<Link to="/">
<button className="center-button-startover">Start Over</button>
</Link>
<div className="form-in">
<form onSubmit={handleSubmit} className="new-customer-form">
<label for="firstName">First Name*</label>
<input
type="text"
name="first_name"
required
// value={firstName}
// onChange={handleInputChange}
/>
<br />
<label for="lastName">Last Name*</label>
<input
type="text"
name="last_name"
required
// value={lastName}
// onChange={handleInputChange}
/>
<br />
<label for="email">Email*</label>
<input
type="email"
className="email"
required
// value={email}
// onChange={handleInputChange}
/>
<br />
<label for="phone">Phone*</label>
<input
type="tel"
className="phone"
required
// value={phone}
// onChange={handleInputChange}
/>
<br />
<label for="nickName">Nickname</label>
<input
type=" text"
className="nickname"
// value={nickName}
// onChange={handleInputChange}
/>
<div className="input-with-optional">
<span className="nick-helper">
(optional) This will be displayed instead of your first name.
</span>
<br />
</div>
<button onSubmit={handleSubmit} type="submit" className="regi">
Register
</button>
</form>
</div>
</div>
</div>
);
}enter code here

You forgot to send a response from your POST route handler. For example:
res.send('Customer created')
Additionally, in your frontend you have a typo (preventDefalut) which will make your code crash.

Related

Getting a specific user from MYSQL with axios Get

I'm at the very end of my project, I'm using react js frontend and express and mysql, I have everything working but the last step, I have a input field that is suppose to allow a user to enter a email or phone number and hit search, It's suppose to search the database and display that user's info, I have it when you hit search it displays all the data from the database, I need it to search and find the data the user is requesting, I can't find any documentation. here is my front end code.
import React, { useState, useEffect } from "react";
import "./Home.css";
import BattleAxe from "./battleaxes.png";
import { Link } from "react-router-dom";
import axios from "axios";
export default function Home() {
const [searchResults, setSearchResults] = useState([]);
const handleSubmit = (e) => {
e.preventDefault();
axios.get("http://localhost:3001/api/get").then((response) => {
setSearchResults(response.data);
});
};
return (
<div className="home-container">
<img src={BattleAxe} alt="" className="axe-image" />
<div>
<h2 className="heading"> Welcome to Battle Axes!</h2>
</div>
<div className="split">
<div className="newc">
<p className="info1">
<strong>First Timer?</strong>
</p>
<p className="info3">
Click the 'New Customer'
<br />
button to get started.
</p>
<Link to="/NewCustomer">
<button className="new-customer">New Customer</button>
</Link>
</div>
<div className="returnc">
<h3 className="info2">Returning Customer?</h3>
<p className="info4">
Enter your Email or Phone
<br />
below to find your acount.
</p>
<form onSubmit={handleSubmit}>
<input type="text" className="text-field" />
<button className="search-btn">Search</button>
</form>
</div>
</div>
<div className="search-results">
{searchResults.map((val) => {
return (
<p className="srlist">
{val.firstName} | {val.lastName}
<br />
<br />
{val.email}
<br />
<br />
{val.phone}
<Link to="/WaiverForm">
<button className="sel-btn">Select</button>
</Link>
</p>
);
})}
</div>
</div>
);
}
here is my backend.
const express = require("express");
const app = express();
const mysql = require("mysql");
const bodyParser = require("body-parser");
const cors = require("cors");
const { response } = require("express");
const db = mysql.createConnection({
host: "localhost",
user: "root",
password: "Killer12!",
database: "cloneDataBase",
});
app.use(cors());
app.use(express.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/api/get", (req, res) => {
const sqlGet = "SELECT * FROM customer_registration";
db.query(sqlGet, (error, result) => {
res.send(result);
});
});
app.post("/api/post", (req, res) => {
const { firstName, lastName, email, phone, nickName } = req.body;
const sqlInsert =
"INSERT INTO customer_registration (firstName, lastName, email, phone, nickName) VALUES (?,?,?,?,?)";
db.query(
sqlInsert,
[firstName, lastName, email, phone, nickName],
(error, result) => {
if (error) {
console.log(error);
res.send("False");
}
}
);
res.send("Customer created");
});
app.post("/api/waiver", (req, res) => {
const userSignature = req.body.userSignature;
const sqlInsert = "INSERT INTO waiver_signature (userSignature) VALUES (?)";
db.query(sqlInsert, userSignature, (err, result) => {
if (err) {
console.log(err);
}
});
res.send("Signature created");
});
app.listen(3001, () => {
console.log("running on port 3001");
});
You can create an endpoint where you are receving query params either email or phone number
app.get("/api/get", (req, res) => {
let email = req.query.email ?? '';
let phone = req.query.phone ?? '';
const sqlGet = "SELECT * FROM customer_registration WHERE email = ? OR phone = ?";
db.query(sqlGet, [email, phone], (error, result) => {
res.send(result);
});
});
In your frontend, you can send data in query params, You can plug in your email and phone like this below
axios.get("http://localhost:3001/api/get", { params: { email: email, phone: phone} })

React prevent Duplicate record input?

How i can prevent duplicate record input especially email and student number And show the message if the registration is accepted or it has duplicate record?
It accept data and when a set the email and the student number unique in the MySQL db it will not accept data but their is no message. It only show message in the terminal of visual studio that the email and student number is unique
Front end
import React from 'react'
import { useState } from 'react';
import Axios from 'axios';
import { useNavigate} from 'react-router-dom'
function Register() {
let navigate= useNavigate();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [student_num , setStudnum] = useState(0);
const [RegisterStatus, setRegisterStatus] = useState("");
const [studentList, setStudentList] = useState([])
const addStudent = ( ) =>{
Axios.post("http://localhost:3001/create", {
email: email,
password: password,
student_num : student_num ,
}).then(()=>{
console.log("sucess")
});
};
return (
<form>
<div className="information">
<div className="App">
<label>Email:</label>
<input type="text" onChange={(event) => {
setEmail(event.target.value);
}} required />
<label>Password:</label>
<input type="password" onChange={(event) => {
setPassword(event.target.value);
}} required/>
<label>Student Number:</label>
<input type="number" onChange={(event) => {
setStudnum(event.target.value);
}}required/>
This is the MySQL connection / backend
app.post("/create", (req, res) => {
const email = req.body.email;
const password = req.body.password;
const student_num = req.body.student_num;
db.query(
"INSERT INTO student (email,passwordstudent_num) VALUES (?,?,?)",
[
email,
password,
student_num,
],
(err, result) => {
if (err) {
console.log(err);
} else {
res.send("Values Inserted");
}
}
);
});

How to fix Converting circular structure to JSON error

I'm working on a project for my portfolio and decided I would do the registration page and backend first so that can be out of the way. I followed a tutorial with nodejs and mysql but I'm getting an error saying TypeError: Converting circular structure to JSON --> starting at object with constructor 'HTMLInputElement' | property '__reactFiber$g76m1cpwrsr' -> object with constructor 'FiberNode' --- property 'stateNode' closes the circle. I can't tell exactly where is error might be originating from or what is causing this issue. Any help would be appreciated
Registration page
import React, { useState } from "react";
import "../Styling/Register.css";
import axios from "axios";
function Register() {
const [userName, setUsername] = useState("");
const [userEmail, setUserEmail] = useState("");
const [userPassword, setUserPassword] = useState("");
const [userSubject, setUserSubject] = useState("");
const [account_type, setAcc_Type] = useState("");
const create_user = () => {
axios
.post("http://localhost:3001/register", {
userID: 1001,
userName: userName,
Email: userEmail,
password: userPassword,
subject: userSubject,
acc_type: account_type,
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
};
return (
<div className="form">
<input
type="text"
placeholder="FULL NAME"
onChange={(e) => setUsername(e.target.value)}
/>
<input
type="text"
placeholder="Email"
onChange={(e) => setUserEmail(e.target.value)}
/>
<input
type="text"
placeholder="Password"
onChange={(e) => setUserPassword(e.target.value)}
/>
<input
type="text"
placeholder="Field/Subject"
onChange={(e) => setUserSubject(e.target.value)}
/>
<input
type="text"
placeholder="Tutor/Student"
onChange={(e) => setAcc_Type(e.target.value)}
/>
<button onClick={create_user}>Register</button>
</div>
);
}
export default Register;
My server side script in nodejs
const express = require('express');
const mysql = require('mysql');
const cors = require('cors');
const app = express();
app.use(express.json())
app.use(cors());
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'tutor_locator'
});
app.post('/register', (req, res) => {
const userID = req.body.userID;
const userName = req.body.userName;
const Email = req.body.userEmail;
const password = req.body.userPassword;
const subject = req.body.userSubject;
const acc_type = req.body.account_type;
db.query(
'INSERT INTO users(User_ID, User_Name, User_Email, user_Password, User_Subject, Accout_Type) VALUES (?,?,?,?,?,?)',
[userID, userName, Email, password, subject, acc_type],
(err, result) => {
console.log(res);
}
)
})
app.listen(3001, () => {
console.log('server started');
});

server crashed down when I was trying to login the data for testing validation

I was trying to input wrong data to see how the server getting data from the database and responding to the client if there is any incorrect like wrong username/password or username does not exist. It worked perfectly and responded for 1 to 2 times until the third time the crash happened:
Cannot set headers after they are sent to the client
ERR_CONNECTION_REFUSED``
Here is my server-side:
const express = require("express");
const router = express.Router();
const { Users } = require("../models");
const bcrypt = require('bcryptjs');
router.post("/", async (req, res) => {
const {username, password, phone, email} = req.body;
const user = await Users.findOne({ where: {username: username}});
if(user) {
res.json({ error: "User is unavailable"});
} else {
bcrypt.hash(password, 10).then((hash) => {
Users.create({
username: username,
password: hash,
phone: phone,
email: email,
});
res.json("SUCCESS");
});
};
});
router.post("/login", async (req, res) => {
const { username, password } = req.body;
const user = await Users.findOne({ where: { username: username } });
if (!user) res.json("User Doesn't exist");
bcrypt.compare(password, user.password).then((match) => {
if (!match) res.json("Wrong Username or Password");
res.json("YOU LOGGED IN");
});
});
module.exports = router;
and Here is my client side:
import {FontAwesomeIcon} from '#fortawesome/react-fontawesome';
import {faUser, faLock, faEye, faEyeSlash} from '#fortawesome/free-solid-svg-icons';
import { BiUser } from "react-icons/bi";
import {Link} from 'react-router-dom';
import { useState } from 'react';
import axios from 'axios';
function Register() {
const [username, setUsername] = useState("");
const [password, setPassword]= useState("");
const [type, setType] = useState("password");
const [icon, setIcon] = useState(faEye);
const handleShowHidePass = () => {
let currentType = type === "password" ? "text" : "password";
let currentIcon = icon === faEye ? faEyeSlash : faEye;
setType(currentType);
setIcon(currentIcon);
}
const login = e => {
e.preventDefault();
axios.post ("http://localhost:3001/auth/login", {
username: username,
password: password,
}).then((res) =>{
console.log(res.data);
});
};
return(
<div className="right">
<span className="title"><BiUser className="tilteIcon"/></span>
<form onSubmit={login} >
<div className="formInput">
<span className="icon"><FontAwesomeIcon icon={faUser}/></span>
<input
type="text"
className="username"
value={username}
placeholder="Username"
onChange={(e) => {
setUsername(e.target.value)
}}
/>
</div>
<div className="formInput">
<span className="icon"><FontAwesomeIcon icon={faLock}/></span>
<input
type={type}
className="password1"
value={password}
placeholder="Password"
onChange={(event) => {
setPassword(event.target.value)
}}
/>
<span className="show"><FontAwesomeIcon icon={icon} onClick={handleShowHidePass}/></span>
</div>
<div className="formInput">
<button type="submit">Sign Up</button>
</div>
<div className="login">
<Link to="/register" style={{textDecoration: 'none'}}>I already have an account!</Link>
</div>
</form>
</div>
);
}
export default Register;
use return with this line if (!user) return res.json("User Doesn't exist");
your code is executing further after sending the response

How do I add a loading spinner in React and Node app? (Nodemailer)

I want to achieve something like when I click on the Send button, a spinner should appear near the button then transform the Send button into a Message Sent button. I could achieve that the button changes, but there is no loading time. Why does it happen immediately?
React Frontend:
import React from 'react';
import './contact.css';
import tick4 from './tick4.svg';
import copy from './copy.svg';
import axios from 'axios';
class Contact extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
phone: '',
loading: false,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
handleSubmit(e) {
e.preventDefault();
const { name, email, phone } = this.state;
axios.post('/api/contact', {
name,
email,
phone,
});
this.resetForm();
}
resetForm() {
this.setState({ name: '', email: '', phone: '', loading: true });
}
render() {
return (
<div className="contact">
<div className="contact-flex">
<div className="contact-right">
<h1>GET IN TOUCH</h1>
<div>
<form onSubmit={this.handleSubmit} method="POST">
<label htmlFor="name">NAME</label>
<br />
<input
onChange={this.handleChange}
value={this.state.name}
type="text"
id="name"
name="name"
placeholder="Your full name..."
required
/>
<br />
<label htmlFor="phone">PHONE</label>
<br />
<input
onChange={this.handleChange}
type="text"
id="phone"
name="phone"
placeholder="Your phone number..."
value={this.state.phone}
required
/>
<br />
<label htmlFor="email">EMAIL</label>
<br />
<input
onChange={this.handleChange}
type="email"
id="email"
name="email"
placeholder="Your email address..."
value={this.state.email}
required
/>
<br />
{!this.state.loading && (
<button className="contact-button" type="submit">
Send
</button>
)}
{this.state.loading && (
<button className="contact-button" type="submit">
Message Sent
</button>
)}
</form>
</div>
</div>
</div>
<div className="copy">
<img src={copy} className="copysvg" alt="copy"></img>
</div>
</div>
);
}
}
export default Contact;
Node Backend (Nodemailer):
var express = require('express');
const bodyParser = require('body-parser');
var nodemailer = require('nodemailer');
const creds = require('./config');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/api/contact', (req, res) => {
nodemailer.createTestAccount((err, account) => {
const htmlEmail = `
Name: ${req.body.name}
Phone: ${req.body.phone}
Email: ${req.body.email}
`;
let transporter = nodemailer.createTransport({
host: 'smtp.ethereal.email',
port: 587,
auth: {
user: 'MYEMAILHERE',
pass: 'MYPASSWORDHERE',
},
});
let mailOptions = {
from: req.body.name,
to: 'TOTHISEMAIL',
subject: 'Potential Client Message From The Workshop',
html: htmlEmail,
};
transporter.sendMail(mailOptions, (err, data) => {
console.log('message sent');
});
});
});
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`server listening on port ${PORT}`);
});
Javascript in the browser is async so when you do post a request, while you getting result this.resetForm function is already called
Make these changes to code:
toggleLoading = () => {
this.setState(prevState => {
loading: !prevState.loading
})
}
handleSubmit(e) {
e.preventDefault();
const { name, email, phone } = this.state;
this.toggleLoading()
axios.post('/api/contact', {
name,
email,
phone,
})
.then(result => {
this.resetForm();
//something
})
.catch(err => {
//something
this.toggleLoading()
});
}
resetForm() {
this.setState({ name: '', email: '', phone: '', loading: false });
}
NOTE: in resetForm change loading to false
Suggestion:
you don't need to write to button for saving. just do this
<button className="contact-button" type="submit">
{this.state.loading ? 'Saving...' : 'Send'}
</button>
You don't need this
this.handleChange = this.handleChange.bind(this);
if you are using the arrow function unless you are using very old react version