Failed to load resource : the server responded with status of 400 - reactjs

import React from 'react';
class Register extends React.Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
name: ''
}
}
onNameChange = (event) => {
this.setState({name: event.target.value})
}
onEmailChange = (event) => {
this.setState({email: event.target.value})
}
onPasswordChange = (event) => {
this.setState({password: event.target.value})
}
onSubmitSignIn = () => {
fetch('https://warm-earth-96837.herokuapp.com/register', {
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
email: this.state.email,
password: this.state.password,
name: this.state.name
})
})
.then(response => response.json())
.then(user => {
if (user.id) {
this.props.loadUser(user)
this.props.onRouteChange('home');
}
})
}
render() {
return (
<article className="br3 ba b--black-10 mv4 w-100 w-50-m w-25-l mw6 shadow-5 center">
<main className="pa4 black-80">
<div className="measure">
<fieldset id="sign_up" className="ba b--transparent ph0 mh0">
<legend className="f1 fw6 ph0 mh0">Register</legend>
<div className="mt3">
<label className="db fw6 lh-copy f6" htmlFor="name">Name</label>
<input
className="pa2 input-reset ba bg-transparent hover-bg-black hover-white w-100"
type="text"
name="name"
id="name"
onChange={this.onNameChange}
/>
</div>
<div className="mt3">
<label className="db fw6 lh-copy f6" htmlFor="email-address">Email</label>
<input
className="pa2 input-reset ba bg-transparent hover-bg-black hover-white w-100"
type="email"
name="email-address"
id="email-address"
onChange={this.onEmailChange}
/>
</div>
<div className="mv3">
<label className="db fw6 lh-copy f6" htmlFor="password">Password</label>
<input
className="b pa2 input-reset ba bg-transparent hover-bg-black hover-white w-100"
type="password"
name="password"
id="password"
onChange={this.onPasswordChange}
/>
</div>
</fieldset>
<div className="">
<input
onClick={this.onSubmitSignIn}
className="b ph3 pv2 input-reset ba b--black bg-transparent grow pointer f6 dib"
type="submit"
value="Register"
/>
</div>
</div>
</main>
</article>
);
}
}
export default Register;
server.js
const express = require('express');
const bodyParser = require('body-parser');
const bcrypt = require('bcrypt-nodejs');
const cors = require('cors');
const knex = require('knex');
const register = require('./controllers/register');
const signin = require('./controllers/signin');
const profile = require('./controllers/profile');
const image = require('./controllers/image');
const db = knex({
client: 'pg',
connection: {
connectionString : process.env.DATABASE_URL,
ssl : true,
}
});
const app = express();
app.use(cors())
app.use(bodyParser.json());
app.get('/', (req, res)=> { res.send('it is working!') })
app.post('/signin', signin.handleSignin(db, bcrypt))
app.post('/register', (req, res) => { register.handleRegister(req, res, db, bcrypt) })
app.get('/profile/:id', (req, res) => { profile.handleProfileGet(req, res, db)})
app.put('/image', (req, res) => { image.handleImage(req, res, db)})
app.post('/imageurl', (req, res) => { image.handleApiCall(req, res)})
app.listen(process.env.PORT || 3000, ()=> {
console.log(`app is running on port ${process.env.PORT}`);
})
App.js
import React, { Component } from 'react';
import Particles from 'react-particles-js';
import FaceRecognition from './components/FaceRecognition/FaceRecognition';
import Navigation from './components/Navigation/Navigation';
import Signin from './components/Signin/Signin';
import Register from './components/Register/Register';
import Logo from './components/Logo/Logo';
import ImageLinkForm from './components/ImageLinkForm/ImageLinkForm';
import Rank from './components/Rank/Rank';
import './App.css';
const particlesOptions = {
//customize this to your liking
particles: {
number: {
value: 30,
density: {
enable: true,
value_area: 800
}
}
}
}
const initialState = {
input: '',
imageUrl: '',
box: {},
route: 'signin',
isSignedIn: false,
user: {
id: '',
name: '',
email: '',
entries: 0,
joined: ''
}
}
class App extends Component {
constructor() {
super();
this.state = initialState;
}
loadUser = (data) => {
this.setState({user: {
id: data.id,
name: data.name,
email: data.email,
entries: data.entries,
joined: data.joined
}})
}
calculateFaceLocation = (data) => {
const clarifaiFace = data.outputs[0].data.regions[0].region_info.bounding_box;
const image = document.getElementById('inputimage');
const width = Number(image.width);
const height = Number(image.height);
return {
leftCol: clarifaiFace.left_col * width,
topRow: clarifaiFace.top_row * height,
rightCol: width - (clarifaiFace.right_col * width),
bottomRow: height - (clarifaiFace.bottom_row * height)
}
}
displayFaceBox = (box) => {
this.setState({box: box});
}
onInputChange = (event) => {
this.setState({input: event.target.value});
}
onButtonSubmit = () => {
this.setState({imageUrl: this.state.input});
fetch('https://warm-earth-96837.herokuapp.com/imageurl', {
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
input: this.state.input
})
})
.then(response => response.json())
.then(response => {
if (response) {
fetch('https://warm-earth-96837.herokuapp.com/image', {
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: this.state.user.id
})
})
.then(response => response.json())
.then(count => {
this.setState(Object.assign(this.state.user, { entries: count}))
})
.catch(console.log)
}
this.displayFaceBox(this.calculateFaceLocation(response))
})
.catch(err => console.log(err));
}
onRouteChange = (route) => {
if (route === 'signout') {
this.setState(initialState)
} else if (route === 'home') {
this.setState({isSignedIn: true})
}
this.setState({route: route});
}
render() {
const { isSignedIn, imageUrl, route, box } = this.state;
return (
<div className="App">
<Particles className='particles'
params={particlesOptions}
/>
<Navigation isSignedIn={isSignedIn} onRouteChange={this.onRouteChange} />
{ route === 'home'
? <div>
<Logo />
<Rank
name={this.state.user.name}
entries={this.state.user.entries}
/>
<ImageLinkForm
onInputChange={this.onInputChange}
onButtonSubmit={this.onButtonSubmit}
/>
<FaceRecognition box={box} imageUrl={imageUrl} />
</div>
: (
route === 'signin'
? <Signin loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
: <Register loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
)
}
</div>
);
}
}
export default App;
import React, { Component } from 'react';
import Particles from 'react-particles-js';
import FaceRecognition from './components/FaceRecognition/FaceRecognition';
import Navigation from './components/Navigation/Navigation';
import Signin from './components/Signin/Signin';
import Register from './components/Register/Register';
import Logo from './components/Logo/Logo';
import ImageLinkForm from './components/ImageLinkForm/ImageLinkForm';
import Rank from './components/Rank/Rank';
import './App.css';
const particlesOptions = {
//customize this to your liking
particles: {
number: {
value: 30,
density: {
enable: true,
value_area: 800
}
}
}
}
const initialState = {
input: '',
imageUrl: '',
box: {},
route: 'signin',
isSignedIn: false,
user: {
id: '',
name: '',
email: '',
entries: 0,
joined: ''
}
}
class App extends Component {
constructor() {
super();
this.state = initialState;
}
loadUser = (data) => {
this.setState({user: {
id: data.id,
name: data.name,
email: data.email,
entries: data.entries,
joined: data.joined
}})
}
calculateFaceLocation = (data) => {
const clarifaiFace = data.outputs[0].data.regions[0].region_info.bounding_box;
const image = document.getElementById('inputimage');
const width = Number(image.width);
const height = Number(image.height);
return {
leftCol: clarifaiFace.left_col * width,
topRow: clarifaiFace.top_row * height,
rightCol: width - (clarifaiFace.right_col * width),
bottomRow: height - (clarifaiFace.bottom_row * height)
}
}
displayFaceBox = (box) => {
this.setState({box: box});
}
onInputChange = (event) => {
this.setState({input: event.target.value});
}
onButtonSubmit = () => {
this.setState({imageUrl: this.state.input});
fetch('https://warm-earth-96837.herokuapp.com/imageurl', {
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
input: this.state.input
})
})
.then(response => response.json())
.then(response => {
if (response) {
fetch('https://warm-earth-96837.herokuapp.com/image', {
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: this.state.user.id
})
})
.then(response => response.json())
.then(count => {
this.setState(Object.assign(this.state.user, { entries: count}))
})
.catch(console.log)
}
this.displayFaceBox(this.calculateFaceLocation(response))
})
.catch(err => console.log(err));
}
onRouteChange = (route) => {
if (route === 'signout') {
this.setState(initialState)
} else if (route === 'home') {
this.setState({isSignedIn: true})
}
this.setState({route: route});
}
render() {
const { isSignedIn, imageUrl, route, box } = this.state;
return (
<div className="App">
<Particles className='particles'
params={particlesOptions}
/>
<Navigation isSignedIn={isSignedIn} onRouteChange={this.onRouteChange} />
{ route === 'home'
? <div>
<Logo />
<Rank
name={this.state.user.name}
entries={this.state.user.entries}
/>
<ImageLinkForm
onInputChange={this.onInputChange}
onButtonSubmit={this.onButtonSubmit}
/>
<FaceRecognition box={box} imageUrl={imageUrl} />
</div>
: (
route === 'signin'
? <Signin loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
: <Register loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
)
}
</div>
);
}
}
export default App;
Register Handler Code
const handleRegister = (req, res, db, bcrypt) => {
const { email, name, password } = req.body;
if (!email || !name || !password) {
return res.status(400).json('incorrect form submission');
}
const hash = bcrypt.hashSync(password);
db.transaction(trx => {
trx.insert({
hash: hash,
email: email
})
.into('login')
.returning('email')
.then(loginEmail => {
return trx('users')
.returning('*')
.insert({
email: loginEmail[0],
name: name,
joined: new Date()
})
.then(user => {
res.json(user[0]);
})
})
.then(trx.commit)
.catch(trx.rollback)
})
.catch(err => res.status(400).json('unable to register'))
}
module.exports = {
handleRegister: handleRegister
};
I am getting error 400 when i am trying to register a user.
Failed to load resource: the server responded with a status of 400 (Bad Request)
i have attached my register.js file
Register.js:26 POST https://warm-earth-96837.herokuapp.com/register 400 (Bad Request)
Register.onSubmitSignIn # Register.js:26
The 400 Bad Request Error is an HTTP response status code that indicates that the server was unable to process the request sent by the client due to invalid syntax. As with the dozens of potential HTTP response codes, receiving a 400 Bad Request Error while accessing your own application can be both frustrating and challenging to fix. Such HTTP response codes represent the complex relationship between the client, a web application, a web server, and often multiple third-party web services, so determining the cause of a particular status code can be a difficult, even within a controlled development environment

The 400 error happens when, for example, your route signup needs a field "name" and you did not send this field, or when you send a field that, for example, should be a string but you sent an Integer. That is, your request is wrong. Please put here what your route request to sign up the user so we can conclude what field is wrong or what is missing.
Thx and waiting for your response :).

Related

How do I persist my next-auth user session? so i could use the ID provided to fetch data in other routes

What I want to achieve here is, whenever a user logs in, I want to store the data returned because the data holds an ID that I would use to fetch data in other routes.
When a user successfully logs in, he would be redirected to the /home route and the ID gotten from the session would be used to fetch data. Everything works fine initially, but if I refresh the home page, the user becomes null.
This is what my [...nextauth].js looks like.
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import axios from "axios";
export default NextAuth({
providers: [
CredentialsProvider({
name: "credentials",
credentials: {
username: { label: "Username", type: "text", placeholder: "justin" },
password: {label: "Password",type: "password",placeholder: "******"},
},
async authorize(credentials, req) {
const url = req.body.callbackUrl.split("/auth")[0];
const { username, password } = credentials;
const user = await axios({
url: `${url}/api/user/login`,
method: "POST",
data: {
username: username,
password: password,
},
"content-type": "application/json",
})
.then((res) => {
return res.data;
})
.catch((err) => {
if (err.response.data) {
throw new Error(err.response.data);
} else {
return null;
}
return null;
});
return user;
},
}),
],
callbacks: {
jwt: ({ token, user }) => {
if (user) {
token.user = user;
}
return token;
},
session: ({ session, token }) => {
if (token) {
session.user = token.user;
}
return session;
},
},
pages: {
signIn: "/auth/login",
newUser: "/auth/register",
},
});
and this is what my /home route looks like
import Card from "#/components/card/Card";
import React, { useEffect, useState } from "react";
import styles from "./home.module.css";
import { Ubuntu } from "#next/font/google";
import { useSession } from "next-auth/react";
import { useDispatch, useSelector } from "react-redux";
const ubuntu = Ubuntu({ weight: "500", subsets: ["cyrillic"] });
const getData = async (id) => {
const res = await fetch({
url: "http://localhost:3000/api/note/getall",
method: "POST",
"content-type": "application/json",
data: {
id: id,
},
});
if (!res.ok) {
console.log(id);
throw new Error("Unable to fetch");
} else {
return res.json();
console.log(res);
}
};
function home() {
const colors = ["#E9F5FC", "#FFF5E1", "#FFE9F3", "#F3F5F7"];
const random = Math.floor(Math.random() * 5);
const rc = colors[random];
const [pop, setPop] = useState("none");
const { user } = useSelector((state) => state.user);
const getDataa = async () => {
console.log(user)
const data = await getData(user._id);
console.log(data);
};
useEffect(() => {
if (user) {
alert(user)
}
}, []);
return (
<div className={styles.home}>
<header>
<h3 className={ubuntu.className}>
Hello, <br /> {user?.username}!
</h3>
<input type="text" placeholder="search" />
</header>
<div className={styles.nav}>
<h1 className={ubuntu.className}>Notes</h1>
</div>
<div className={styles.section}>
<div className={styles.inner}>
{/* {data &&
data.map((e) => (
<Card
rawData={e}
color={colors[Math.floor(Math.random() * colors.length)]}
/>
))} */}
</div>
</div>
<div className="new"></div>
</div>
);
}
export default home;
Add this component to your App.js file :
function Auth({ children }) {
const router = useRouter();
const { status } = useSession({
required: true,
onUnauthenticated() {
router.push("/sign-in");
},
});
if (status === "loading") {
return <div>Loading ...</div>;
}
return children;
}
Now in your App function instead of returning <Component {...pageProps} /> you check first if the component has auth property, so you wrapp it with <Auth> to ensure that every component that requires session will only mount when the session finishes loading (that's why the user is null because the session is still loading)
{
Component.auth ? (
<Auth>
<Component {...pageProps} />
</Auth>
) : (
<Component {...pageProps} />
);
}
finally you add .auth = {} to every page in whitch you want the session to be defined (Home in your case)
const Home = () => {
//....
}
Home.auth = {};
This also helps to redirect user to /sign-in page if the session is expired
This code seems like it would create a problem / race-condition since you're mixing two different async promise handling styles:
const user = await axios({
url: `${url}/api/user/login`,
method: "POST",
data: {
username: username,
password: password,
},
"content-type": "application/json",
})
.then((res) => {
return res.data;
})
.catch((err) => {
if (err.response.data) {
throw new Error(err.response.data);
} else {
return null;
}
return null;
});
return user;
It should either be this:
try {
const user = await axios({
url: `${url}/api/user/login`,
method: "POST",
data: {
username: username,
password: password,
},
"content-type": "application/json",
});
return user.data;
} catch (err) {
if (err.response.data) {
throw new Error(err.response.data);
} else {
return null;
}
}
Or this:
axios({
url: `${url}/api/user/login`,
method: "POST",
data: {
username: username,
password: password,
},
"content-type": "application/json",
}).then((res) => {
return res.data;
}).catch((err) => {
if (err.response.data) {
throw new Error(err.response.data);
} else {
return null;
}
return null;
});

React Js : Unable to login until page gets refresh manually

As a beginner to the React Js I'm trying simple projects for hands-on experience and to learn as well! so, in the same way I've created one login portal with react js and WAMP server by watching YouTube tutorial
in the middle I went through some errors but somehow I managed and get them off but after completing the project when I'm trying to login with the credentials which I've given in database the response and all was clear but the page doesn't redirect to welcome page after clicking on login button instead it redirects to welcome page after refreshing manually. I couldn't identify the mistake in my code.
LoginForm.js
import React from 'react';
import InputField from './InputField';
import SubmitButton from './SubmitButton';
import UserStore from './stores/UserStore';
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
buttonDisabled: false
}
}
setInputValue(property, val) {
val = val.trim();
if (val.length > 12) {
return;
}
this.setState({
[property]: val
})
}
resetForm() {
this.setState({
username: "",
password: "",
buttonDisabled: false
})
}
async doLogin() {
if (!this.state.username) {
return;
}
if (!this.state.password) {
return;
}
this.setState({
buttonDisabled: true
})
try {
let res = await fetch('/login', {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password
})
});
let result = await res.json();
if (result && result.succes) {
UserStore.isLoggedIn = true;
UserStore.username = result.username;
}
else if (result && result.succes === false) {
this.resetForm();
alert(result.msg);
}
} catch (e) {
console.log(e);
this.resetForm();
}
}
render() {
return (
<div className="loginForm">
Log In
<InputField
type='text'
placeholder='Username'
value={this.state.username ? this.state.username : ''}
onChange={(val) => this.setInputValue('username', val)}
/>
<InputField
type='password'
placeholder='Password'
value={this.state.password ? this.state.password : ''}
onChange={(val) => this.setInputValue('password', val)}
/>
<SubmitButton
text='Log In'
disabled={this.state.buttonDisabled}
onClick={() => this.doLogin()}
/>
</div>
);
}
}
export default LoginForm;
SubmitButton.js
import React from 'react';
class SubmitButton extends React.Component {
render() {
return (
<div className="submitButton">
<button
className='btn'
type='submit'
disabled={this.props.disabled}
onClick={() => this.props.onClick()}
>
{this.props.text}
</button>
</div>
);
}
}
export default SubmitButton;
App.js
import React from 'react';
import { observer } from 'mobx-react';
import UserStore from './stores/UserStore';
import LoginForm from './LoginForm';
import SubmitButton from './SubmitButton';
import './App.css';
class App extends React.Component {
async componentDidMount() {
try {
let res = await fetch('/isLoggedIn', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
let result = await res.json();
if (result && result.success) {
UserStore.loading = false;
UserStore.isLoggedIn = true;
UserStore.username = result.username;
}
else {
UserStore.loading = false;
UserStore.isLoggedIn = false;
}
}
catch (e) {
UserStore.loading = false;
UserStore.isLoggedIn = false;
}
}
async doLogout() {
try {
let res = await fetch('/logout', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
});
let result = await res.json();
if (result && result.success) {
UserStore.isLoggedIn = false;
UserStore.username = '';
}
}
catch (e) {
console.log(e);
}
}
render() {
if (UserStore.loading) {
return (
<div className="app">
<div className='container'>
Loading ,Please Wait...
</div>
</div>
);
}
else {
if (UserStore.isLoggedIn) {
return (
<div className="app">
<div className='container'>
Welcome {UserStore.username}
<SubmitButton
text={'Log Out'}
disabled={false}
onClick={() => this.doLogout()}
/>
</div>
</div>
);
}
return (
<div className="app">
<div className='container'>
<LoginForm />
</div>
</div>
);
}
}
}
export default observer(App);
Router.js
const bcrypt = require('bcrypt');
class Router {
constructor(app, db) {
this.login(app, db);
this.logout(app, db);
this.isLoggedIn(app, db);
}
login(app, db) {
app.post('/login', (req, res) => {
let username = req.body.username;
let password = req.body.password;
username = username.toLowerCase();
if (username.length > 12 || password.length > 12) {
res.json({
success: false,
msg: 'An error occured,please try again'
})
return;
}
let cols = [username];
db.query('SELECT * FROM user WHERE username =? LIMIT 1', cols, (err, data, fields) => {
if (err) {
res.json({
success: false,
msg: 'An error occured,please try again'
});
return;
}
if (data && data.length === 1) {
bcrypt.compare(password, data[0].password, (bcryptErr, verified) => {
if (verified) {
req.session.userID = data[0].id;
res.json({
success: true,
username: data[0].username
})
return;
}
else {
res.json({
success: false,
msg: 'Invalid Password'
})
}
});
} else {
res.json({
success: false,
msg: 'User not Found,please try again..!'
})
}
});
});
}
logout(app, db) {
app.post('/logout',(req,res)=>{
if(req.session.userID){
req.session.destroy();
res.json({
success:true
})
return true;
}
else{
res.json({
success:false
})
return false;
}
})
}
isLoggedIn(app, db) {
app.post('/isLoggedIn',(req,res)=>{
if(req.session.userID){
let cols =[req.session.userID];
db.query('SELECT * FROM user WHERE ID=? LIMIT 1',cols,(err,data,fields) =>{
if(data && data.length ===1){
res.json({
success:true,
username:data[0].username
});
return true;
}
else{
res.json({
success:false
});
}
});
}
else{
res.json({
success:false
})
}
});
}
}
module.exports = Router;
you have to change some logic in LoginForm.js. There are multiple ways in which you can do that. I am showing you one example.
import React from 'react';
import InputField from './InputField';
import SubmitButton from './SubmitButton';
import UserStore from './stores/UserStore';
import {Redirect} from 'react-router-dom' //add a redirect from react-router-dom
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
buttonDisabled: false,
redirectToRefer : false //add a state here for redirect
}
}
setInputValue(property, val) {
val = val.trim();
if (val.length > 12) {
return;
}
this.setState({
[property]: val
})
}
resetForm() {
this.setState({
username: "",
password: "",
buttonDisabled: false
})
}
async doLogin() {
if (!this.state.username) {
return;
}
if (!this.state.password) {
return;
}
this.setState({
buttonDisabled: true
})
try {
let res = await fetch('/login', {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password
})
});
let result = await res.json();
if (result && result.succes) {
UserStore.isLoggedIn = true;
UserStore.username = result.username;
this.setState({redirectToRefer:true})//set rediectToRefer as true
}
else if (result && result.succes === false) {
this.resetForm();
alert(result.msg);
}
} catch (e) {
console.log(e);
this.resetForm();
}
}
render() {
//add a condition at render if redirectToRefer is true then redirect to your page
if(redirectToRefer)
{
return <Redirect to ="/"/>
}
return (
<div className="loginForm">
Log In
<InputField
type='text'
placeholder='Username'
value={this.state.username ? this.state.username : ''}
onChange={(val) => this.setInputValue('username', val)}
/>
<InputField
type='password'
placeholder='Password'
value={this.state.password ? this.state.password : ''}
onChange={(val) => this.setInputValue('password', val)}
/>
<SubmitButton
text='Log In'
disabled={this.state.buttonDisabled}
onClick={() => this.doLogin()}
/>
</div>
);
}
}
export default LoginForm;

Curl works but React App throwing Cannot POST / error while using Axios and Express

I am trying to implement a simple form to send email. The error that I am getting is
Cannot POST /
I've used Create React App and the App.js looks like below:-
import React, { Component } from 'react';
//import logo from './logo.svg';
import './App.css';
import axios from 'axios';
import renderEmail from 'axios';
import MyEmail from 'axios';
class App extends Component {
state = {
data: null
};
componentDidMount() {
// Call our fetch function below once the component mounts
this.callBackendAPI()
.then(res => this.setState({ data: res.express }))
.catch(err => console.log(err));
}
// Fetches our GET route from the Express server
callBackendAPI = async () => {
const response = await fetch('/express_backend');
const body = await response.json();
if (response.status !== 200) {
throw Error(body.message)
}
return body;
};
handleSubmit(event){
const messageHtml = renderEmail(
<MyEmail name={this.state.name}> {this.state.feedback}</MyEmail>
);
axios({
method: "POST",
url:"http://localhost:3000/send",
data: {
name: this.state.name,
email: this.state.email,
messageHtml: messageHtml
}
}).then((response)=>{
if (response.data.msg === 'success'){
alert("Email sent, awesome!");
this.resetForm()
}else if(response.data.msg === 'fail'){
alert("Oops, something went wrong. Try again")
}
})
}
resetForm(){
this.setState({feedback: ''});
}
render() {
return (
<form id="contact-form" method="POST">
<div className="form-group">
<label htmlFor="name">Name</label>
<input type="text" className="form-control" id="name" />
</div>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
</div>
<div className="form-group">
<label htmlFor="message">Message</label>
<textarea className="form-control" rows="5" id="message"></textarea>
</div>
<button type="submit" className="btn btn-primary" onClick={this.handleSubmit}>Submit</button>
</form>
);
}
}
export default App;
The server.js look like the below:-
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
var nodemailer = require('nodemailer');
const creds = require('./config');
// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));
// create a GET route
app.get('/express_backend', (req, res) => {
res.send({ express: 'YOUR EXPRESS BACKEND IS CONNECTED TO REACT' });
});
var transport = {
host: 'host', // e.g. smtp.gmail.com
//service: 'gmail',
port: 465,
secure: true,
auth: {
user: 'xxxxx',
pass: 'xxxxx'
},
tls: {
// do not fail on invalid certs
rejectUnauthorized: false
}
}
var transporter = nodemailer.createTransport(transport)
transporter.verify((error, success) => {
if (error) {
console.log(error);
} else {
console.log('All works fine, congratz!');
}
});
app.use(express.json());
app.post('/send', (req, res, next) => {
const name = req.body.name
const email = req.body.email
const message = req.body.messageHtml
var mail = {
from: name,
to: 'abc#gmail.com',
subject: 'Contact form',
html: message
}
transporter.sendMail(mail, (err, data) => {
if (err) {
res.json({
msg: 'fail'
})
} else {
res.json({
msg: 'success'
})
}
})
});
I have checked with curl and the localhost:3000/send is working properly and returns success. Please help! Thank you.
Have you tried enabling CORS in your server so as to enable React interact with your back end server?

React + Express sending data?

I'm working on a login/register system with React front-end and Node/Express back-end.
When the registration fails, i want to reload the registration page and return the error msgs to my react front end.
Instead of refreshing the page, it renders the JSON data.
How can you go about re-rendering the registration form, while sending the data behind the scenes?
router.post("/register", (req, res) => {
const { name, email, password, password2 } = req.body;
let errors = [];
...
...
...
if (errors.length > 0) {
res.send({
errors,
name,
email,
password,
password2
});
You need to receive the response from express in your react app, and perform your logic inside your submit function in react.
One way you can do this is to create a state variable for the error message. Make the initial value null or ''. When user registration fails catch the error and assign it your error variable in state. Here is an example of user registration system:
//RegistrationForm.js
import React, { useState } from 'react';
import AuthApiService from '../../services/auth-api-service';
import { Input } from '../Utils/Utils';
import { Button } from '#material-ui/core';
import './RegistrationForm.css';
export default function RegistrationForm(props) {
const [error, setError] = useState(null)
const errorDiv = error
? <div className="error">
<i class="material-icons error-icon">error_outline</i>
{error}
</div>
: '';
const handleSubmit = e => {
e.preventDefault();
setError(null);
const { full_name, user_name, password } = e.target;
AuthApiService.postUser({
full_name: full_name.value,
user_name: user_name.value,
password: password.value
})
.then(user => {
full_name.value = '';
user_name.value = '';
password.value = '';
props.onRegistrationSuccess();
})
.catch(res => {
setError(res.error);
})
};
return(
<form className='RegistrationForm'
onSubmit={handleSubmit}
>
<div className='full_name'>
<label htmlFor='RegistrationForm__full_name'>
Full name
</label>
<Input
name='full_name'
type='text'
required
id='RegistrationForm__full_name'>
</Input>
</div>
<div className='user_name'>
<label htmlFor='RegistrationForm__user_name'>
User name
</label>
<Input
name='user_name'
type='text'
required
id='RegistrationForm__user_name'>
</Input>
</div>
<div className='password'>
<label htmlFor='RegistrationForm__password'>
Password
</label>
<Input
name='password'
type='password'
required
id='RegistrationForm__password'
>
</Input>
</div>
<div className='confirm-password'>
<label htmlFor="LoginForm__confirm-password">
Retype Password
</label>
<Input
name='confirm-password'
type="password"
required
id="LoginForm__confirm-password">
</Input>
</div>
{errorDiv}
<Button type='submit' variant='contained' color='default'>
Register
</Button>
</form>
)
}
//AuthApiService.js
import config from '../config';
import TokenService from './token-service';
import IdleService from './idle-service';
const AuthApiService = {
postUser(user) {
return fetch(`${config.API_ENDPOINT}/users`, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(user)
})
.then(res =>
(!res.ok)
? res.json().then(e => Promise.reject(e))
: res.json()
)
.then(res => {
TokenService.saveAuthToken(res.authToken)
IdleService.registerIdleTimerResets()
TokenService.queueCallbackBeforeExpiry(() => {
AuthApiService.postRefreshToken()
})
return res
})
},
postLogin({user_name, password }) {
return fetch(`${config.API_ENDPOINT}/auth/login`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({user_name, password}),
})
.then(res =>
(!res.ok)
? res.json().then(e => Promise.reject(e))
: res.json()
)
.then(res => {
TokenService.saveAuthToken(res.authToken)
TokenService.queueCallbackBeforeExpiry(() => {
AuthApiService.postRefreshToken()
})
return res
})
},
postGuestLogin() {
return fetch(`${config.API_ENDPOINT}/auth/guest-login`, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
})
.then(res =>
(!res.ok)
? res.json().then(e => Promise.reject(e))
: res.json()
)
.then(res => {
TokenService.saveAuthToken(res.authToken)
TokenService.queueCallbackBeforeExpiry(() => {
AuthApiService.postRefreshToken()
})
return res
})
},
postRefreshToken() {
return fetch(`${config.API_ENDPOINT}/auth/refresh`, {
method: 'POST',
headers: {
'authorization': `Bearer ${TokenService.getAuthToken()}`,
},
})
.then(res =>
(!res.ok)
? res.json().then(e => Promise.reject(e))
: res.json()
)
.then(res => {
TokenService.saveAuthToken(res.authToken)
TokenService.queueCallbackBeforeExpiry(() => {
AuthApiService.postRefreshToken()
})
return res
})
.catch(err => {
TokenService.clearAuthToken()
console.log('refresh token request error')
console.log(err)
})
}
}
export default AuthApiService;
//TokenService.js
import jwtDecode from 'jwt-decode';
import config from '../config';
let _timeoutId;
const _TEN_SECONDS_IN_MS = 10000;
const TokenService = {
saveAuthToken(token) {
window.localStorage.setItem(config.TOKEN_KEY, token);
},
getAuthToken() {
return window.localStorage.getItem(config.TOKEN_KEY);
},
clearAuthToken() {
window.localStorage.removeItem(config.TOKEN_KEY);
},
hasAuthToken() {
return !!TokenService.getAuthToken()
},
makeBasicAuthToken(userName, password) {
return window.btoa(`${userName}:${password}`);
},
parseJwt(jwt) {
return jwtDecode(jwt);
},
readJwtToken() {
return TokenService.parseJwt(TokenService.getAuthToken());
},
_getMsUntilExpiry(payload) {
return (payload.exp * 1000) - Date.now();
},
queueCallbackBeforeExpiry(callback) {
const msUntilExpiry = TokenService._getMsUntilExpiry(
TokenService.readJwtToken()
);
_timeoutId = setTimeout(callback, msUntilExpiry - _TEN_SECONDS_IN_MS);
},
clearCallbackBeforeExpiry() {
clearTimeout(_timeoutId);
}
};
export default TokenService;
EDIT:
Here is an example of what the router can look like:
//users-router.js
const express = require('express')
const path = require('path')
const UsersService = require('./users-service')
const AuthService = require('../auth/auth-service')
const usersRouter = express.Router()
const jsonBodyParser = express.json()
usersRouter.post('/', jsonBodyParser, (req, res, next) => {
const { password, user_name, full_name } = req.body
for (const field of ['password', 'full_name', 'user_name'])
if (!req.body[field])
return res.status(400).json({
error: `Missing ${field} in request body`
})
const passwordError = UsersService.validatePassword(password)
if (passwordError)
return res.status(400).json({ error: passwordError })
UsersService.hasUserWithUserName(
req.app.get('db'),
user_name
)
.then(hasUserWithUserName => {
if(hasUserWithUserName)
return res.status(400).json({ error: 'Username already taken' })
return UsersService.hashPassword(password)
.then(hashedPassword => {
const newUser = {
user_name,
full_name,
password: hashedPassword,
date_created: 'now()'
}
return UsersService.insertUser(
req.app.get('db'),
newUser
)
.then(user => {
const serializedUser = UsersService.serializeUser(user)
const { user_name, user_id } = serializedUser
const sub = user_name
const payload = {user_id: user_id}
res
.status(201)
.location(path.posix.join(req.originalUrl, `/${user.id}`))
.send({
authToken: AuthService.createJwt(sub, payload),
user: serializedUser
})
})
})
})
.catch(next)
})
module.exports = usersRouter
//users-service.js
const bcrypt = require('bcryptjs')
const xss = require('xss')
const REGEX_UPPER_LOWER_NUMBER_SPECIAL = /(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&])[\S]+/
const UsersService = {
hasUserWithUserName(db, user_name) {
return db('askify_users')
.where({ user_name })
.first()
.then(user => !!user)
},
insertUser(db, newUser) {
return db
.insert(newUser)
.into('askify_users')
.returning('*')
.then(([user]) => user)
},
validatePassword(password) {
if (password.length < 8) {
return 'Password must be longer than 8 characters'
}
if (password.length > 72) {
return 'Password must be less than 72 characters'
}
if (password.startsWith(' ') || password.endsWith(' ')) {
return 'Password must not start or end with empty spaces'
}
if (!REGEX_UPPER_LOWER_NUMBER_SPECIAL.test(password)) {
return 'Password must contain one upper case, lower case, number and special character'
}
return null
},
hashPassword(password) {
return bcrypt.hash(password, 12)
},
serializeUser(user) {
return {
id: user.id,
full_name: xss(user.full_name),
user_name: xss(user.user_name),
nickname: xss(user.nick_name),
date_created: new Date(user.date_created),
}
},
}
module.exports = UsersService
// auth-service.js
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const config = require('../config')
const AuthService = {
getUserWithUserName(db, user_name) {
return db('askify_users')
.where({user_name})
.first()
},
comparePasswords(password, hash) {
return bcrypt.compare(password, hash)
},
createJwt(subject, payload) {
return jwt.sign(payload, config.JWT_SECRET, {
subject,
expiresIn: config.JWT_EXPIRY,
algorithm: 'HS256',
})
},
verifyJwt(token) {
return jwt.verify(token, config.JWT_SECRET, {
algorithms: ['HS256'],
})
},
parseBasicToken(token) {
return Buffer
.from(token, 'base64')
.toString()
.split(':')
},
}
module.exports = AuthService

React render component after array finished rendering

I am making an api call on componentDidMount the problem is that the api takes some seconds to responde in the meanwhile the user could choose to go to another page
doing so another request is made, if this happens the app crashes. How do fix this issue? for the fix I just need to render the pagination component only when all the array is rendered how do I do so?
import React, { Component, Fragment } from "react";
import Episode from "../components/Episode";
import "react-virtualized/styles.css"; // only needs to be imported once
import { withStyles } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
import Grid from "#material-ui/core/Grid";
import Paper from "#material-ui/core/Paper";
import ButtonBase from "#material-ui/core/ButtonBase";
import CircularProgress from "#material-ui/core/CircularProgress";
import Like from "#material-ui/icons/ThumbUp";
import IconButton from "#material-ui/core/IconButton";
import NextButton from "#material-ui/icons/NavigateNext";
import PreviousButton from "#material-ui/icons/NavigateBefore";
// This example assumes you have a way to know/load this information
const styles = theme => ({
//styles
});
class SeriesPage extends Component {
constructor(props) {
super(props);
this.state = {
apiToken: "",
serie: {
image: "",
description: "",
title: "",
likes: 0,
type: "",
apiName: ""
},
startEpisode: 1,
endEpisode: 10,
episodes: [],
loaded: false,
clicked: false,
enabled: true
};
}
componentDidMount() {
this.initialize(this.state.startEpisode, this.state.endEpisode);
}
initialize = async (startIndex, stopIndex) => {
await this.getTokenFromApi();
await this.getSerieDetailsByApiName();
await this.getEpisodeBySeriesApiNameWithRange(startIndex, stopIndex);
};
getTokenFromApi = async () => {
const data = {
name: "generateToken",
param: {
email: "*",
pass: "*"
}
};
return fetch("*", {
method: "post",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
this.setState({
episodes: "Network request failed"
});
throw Error("Network request failed");
}
return response;
})
.then(res => {
return res.json();
})
.then(content => {
if (content.response.status === 200) {
this.setState({
apiToken: content.response.result.token
});
}
})
.catch(error => {
this.setState({
episodes: "There was an internal error"
});
throw error;
});
};
getSerieDetailsByApiName = async () => {
const data = {
name: "*",
param: {
serieApiName: this.props.match.params.series
}
};
return fetch("*", {
method: "post",
headers: {
Authorization: "Bearer " + this.state.apiToken,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
this.setState({
episodes: "Network request failed"
});
throw Error("Network request failed");
}
return response;
})
.then(response => {
return response.json(); //response.json() is resolving its promise. It waits for the body to load
})
.then(responseData => {
if (responseData.response.status === 200) {
this.setState(
{
serie: responseData.response.result,
loaded: true
},
() => {
console.log(this.state);
}
);
}
})
.catch(error => {
this.setState({
episodes: "There was an internal error"
});
throw error;
});
};
getEpisodeBySeriesApiNameWithRange = async (startIndex, stopIndex) => {
const data = {
name: "*",
param: {
serieApiName: this.props.match.params.series,
startIndex: startIndex,
stopIndex: stopIndex
}
};
return fetch("*", {
method: "post",
headers: {
Authorization: "Bearer " + this.state.apiToken,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
this.setState({
episodes: "Network request failed"
});
throw Error("Network request failed");
}
return response;
})
.then(response => {
return response.json(); //response.json() is resolving its promise. It waits for the body to load
})
.then(responseData => {
if (responseData.response.status === 200) {
this.setState(prevState => ({
episodes: [...prevState.episodes, ...responseData.response.result]
}));
}
})
.catch(error => {
this.setState({
episodes: "There was an internal error"
});
});
};
handleLikeClick = () => {
if (this.state.clicked) {
this.setState(
prevState => ({
clicked: !prevState.clicked,
serie: {
...prevState.serie,
likes: Number(prevState.serie.likes) - 1
}
}),
() => {
const data = {
name: "removeLikeSerie",
param: {
serieApiName: this.state.serie.apiName
}
};
return fetch("*", {
method: "post",
headers: {
Authorization: "Bearer " + this.state.apiToken,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
this.setState({
episodes: "Network request failed"
});
throw Error("Network request failed");
}
return response;
})
.catch(error => {
this.setState({
episodes: "There was an internal error"
});
});
}
);
} else {
this.setState(
prevState => ({
clicked: !prevState.clicked,
serie: {
...prevState.serie,
likes: Number(prevState.serie.likes) + 1
}
}),
() => {
const data = {
name: "likeSerie",
param: {
serieApiName: this.state.serie.apiName
}
};
return fetch("*", {
method: "post",
headers: {
Authorization: "Bearer " + this.state.apiToken,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
this.setState({
episodes: "Network request failed"
});
throw Error("Network request failed");
}
return response;
})
.catch(error => {
this.setState({
episodes: "There was an internal error"
});
});
}
);
}
};
previousPage = () => {
if (this.state.startEpisode === 11) {
this.setState(
prevState => ({
episodes: [],
startEpisode: prevState.startEpisode - 10,
endEpisode: prevState.endEpisode - 10,
enabled: true
}),
() => {
this.initialize(this.state.startEpisode, this.state.endEpisode);
}
);
} else if (this.state.startEpisode > 10) {
this.setState(
prevState => ({
episodes: [],
startEpisode: prevState.startEpisode - 10,
endEpisode: prevState.endEpisode - 10
}),
() => {
this.initialize(this.state.startEpisode, this.state.endEpisode);
}
);
}
};
nextPage = () => {
this.setState(
prevState => ({
episodes: [],
startEpisode: prevState.startEpisode + 10,
endEpisode: prevState.endEpisode + 10,
enabled: false
}),
() => {
this.initialize(this.state.startEpisode, this.state.endEpisode);
}
);
};
renderRow = item => {
const { classes, headerIsHidden, ...other } = this.props;
return <Episode key={item.videoId} episode={item} {...other} />;
};
// Render your list
render() {
const { classes } = this.props;
return (
<Fragment>
<div className={classes.serieDetails}>
{this.state.loaded ? (
<Paper className={classes.root}>
<Grid container spacing={16}>
<Grid item>
<ButtonBase className={classes.image}>
<img
className={classes.img}
alt={this.state.serie.title + " Image"}
src={this.state.serie.image}
/>
</ButtonBase>
</Grid>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={16}>
<Grid item xs>
<Typography gutterBottom variant="subtitle1">
{this.state.serie.title}
</Typography>
<Typography gutterBottom>
{this.state.serie.description}
</Typography>
<Typography color="textSecondary">
<IconButton
className={classes.button}
className={this.state.clicked ? classes.liked : ""}
aria-label="Like this serie"
onClick={this.handleLikeClick}
>
<Like />
</IconButton>
{this.state.serie.likes}
</Typography>
</Grid>
</Grid>
</Grid>
</Grid>
</Paper>
) : (
""
)}
</div>
<div className={classes.content}>
<div className={classes.innerContent}>
{this.state.episodes.constructor === String ? (
this.state.episodes
) : (
<div>
{this.state.episodes.map(this.renderRow)}
<div className={classes.pagination}>
<IconButton
aria-label="Previous"
className={classes.button}
onClick={this.previousPage}
disabled={this.state.enabled}
>
<PreviousButton />
</IconButton>
<IconButton
aria-label="Next"
className={classes.button}
onClick={this.nextPage}
>
<NextButton />
</IconButton>
</div>
</div>
)}
</div>
</div>
</Fragment>
);
}
}
export default withStyles(styles, { withTheme: true })(SeriesPage);
The pagination component is the div with className={classes.pagination}
the array is stored in the state
Add to your state a variable called loading which is initially true:
state = {
...,
loading: true
}
After the response return of getEpisodeBySeriesApiNameWithRange you can setState of loading to be false:
getEpisodeBySeriesApiNameWithRange = async (startIndex, stopIndex) => {
const data = {
name: "*",
param: {
serieApiName: this.props.match.params.series,
startIndex: startIndex,
stopIndex: stopIndex
}
};
return fetch("*", {
method: "post",
headers: {
Authorization: "Bearer " + this.state.apiToken,
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
this.setState({
episodes: "Network request failed",
loading: false
});
throw Error("Network request failed");
}
return response;
})
.then(response => {
return response.json(); //response.json() is resolving its promise. It waits for the body to load
})
.then(responseData => {
if (responseData.response.status === 200) {
this.setState(prevState => ({
episodes: [...prevState.episodes, ...responseData.response.result],
loading: false
}));
}
})
.catch(error => {
this.setState({
episodes: "There was an internal error",
loading: false
});
});
};
When you click on nextPage or previousPage setState of loading to be true again:
nextPage = () => {
this.setState(
prevState => ({
episodes: [],
startEpisode: prevState.startEpisode + 10,
endEpisode: prevState.endEpisode + 10,
enabled: false,
loading: true
}),
() => {
this.initialize(this.state.startEpisode, this.state.endEpisode);
}
);
};
the previousPage will be the same.
In render you will only render the component if the loading is false which mean the data is fetched:
{this.state.loading ? null : <div className={classes.content}>
<div className={classes.innerContent}>
{this.state.episodes.constructor === String ? (
this.state.episodes
) : (
<div>
{this.state.episodes.map(this.renderRow)}
<div className={classes.pagination}>
<IconButton
aria-label="Previous"
className={classes.button}
onClick={this.previousPage}
disabled={this.state.enabled}
>
<PreviousButton />
</IconButton>
<IconButton
aria-label="Next"
className={classes.button}
onClick={this.nextPage}
>
<NextButton />
</IconButton>
</div>
</div>
)}
</div>
</div>
}

Resources