I am trying to set up a user register form using react and then sending the inputs to the express backend api to register the new user. I keep gettting the error: Register.js:19 POST http://localhost:3000/api/register 400 (Bad Request) and: error: SyntaxError: Unexpected token B in JSON at position 0 on the client side. On the server side I try and console.log(req.body) and only an empty object gets returned.
My react register code
import React from 'react'
class Register extends React.Component {
state = {
name: "",
username: "",
password: ""
}
handleChange = event => {
const { name, value } = event.target
this.setState({[name]:value})
}
handleSubmit = event => {
event.preventDefault();
fetch("/api/register", {
method: "POST",
body: JSON.stringify(this.state),
headers: {
'Content-Type': 'application/json'
}
}).then(res => res.json())
.then(response => console.log("success:", JSON.stringify(response)))
.catch(error => console.log("error:", error));
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input type="text" name="name" value={this.state.name} placeholder="name" onChange={this.handleChange} />
<input type="text" name="username" value={this.state.username} placeholder="username" onChange={this.handleChange} />
<input type="password" name="password" value={this.state.password} placeholder="password" onChange={this.handleChange} />
<button>Register</button>
</form>
</div>
)
}
}
export default Register
Server side code
const express = require("express"),
passport = require("passport"),
User = require("../models/user");
const router = express.Router({mergeParams: true});
// /api before this
router.post("/register", (req, res)=>{
console.log(req.body);
const newUser = new User({
username: req.body.username,
name: req.body.name
});
User.register(newUser, req.body.password, (err, user)=>{
if(err) {
console.log(err);
}
passport.authenticate("local")(req, res, ()=>{
res.json(user);
});
});
});
module.exports = router;
Related
I am devloping a webapp with nodejs and reactjs with redux. I am trying to make a request to register a new user but i am getting a bad request.
This is the error i am getting:
POST http://localhost:5000/api/users 400 bad request
This is my users route:
const express = require('express');
const config = require('config');
const router = express.Router();
const gravatar = require('gravatar');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { check , validationResult } = require('express-validator/');
const User = require('../../models/User');
//#route POST api/users
//#desc Register user
//#access public
router.post('/', [
check('name', 'Name is required')
.not()
.isEmpty(),
check('email', 'Plese include a valid email').isEmail(),
check('password', 'Please enter a password with 6 or more characters').isLength({min:6})
],
async (req, res)=> {
const errors = validationResult(req);
if(!errors.isEmpty()){
return res.status(400).json({ errors:errors.array()}); //400 is for bad requests
}
const { name, email, password } = req.body;
try{
//See if user exists
let user = await User.findOne({ email });
if(user){
return res.status(400).json({ errors: [{ msg:'User already exists' }] });
}
//Get users gravatar
const avatar = gravatar.url(email,{
s:'200',
r:'pg',
d:'mm'
})
user = new User({
name,
email,
avatar,
password
});
//Encrypt password
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
//Return jsonwebtoken -> this for users to be logged in right after registration
const payload = {
user:{
id: user.id
}
}
jwt.sign(
payload,
config.get('jwtSecret'),
{expiresIn: 360000}, //change to 3600 for production
(err, token)=>{
if(err) throw err;
res.json({ token });
}
)
}catch(err){
console.error('err.message');
res.status(500).send('Server Error');
}
});
module.exports = router;
The route is not the problem i think because if i register manually a user via postman it works.
This is my register.js component:
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { Link, Navigate } from 'react-router-dom';
import { setAlert } from '../../actions/alert';
import { register } from '../../actions/auth';
import PropTypes from 'prop-types';
const Register = ({ setAlert, register }) => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
password2: ''
});
const { name, email, password, password2 } = formData;
const onChange = (e) =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = async (e) => {
e.preventDefault();
if (password !== password2) {
setAlert('Passwords do not match', 'danger');
} else {
register({ name, email, password });
console.log('SUCCESS')
}
};
return (
<section className="container">
<h1 className="large text-primary">Sign Up</h1>
<p className="lead">
<i className="fas fa-user" /> Create Your Account
</p>
<form className="form" onSubmit={onSubmit}>
<div className="form-group">
<input
type="text"
placeholder="Name"
name="name"
value={name}
onChange={onChange}
/>
</div>
<div className="form-group">
<input
type="email"
placeholder="Email Address"
name="email"
value={email}
onChange={onChange}
/>
<small className="form-text">
This site uses Gravatar so if you want a profile image, use a
Gravatar email
</small>
</div>
<div className="form-group">
<input
type="password"
placeholder="Password"
name="password"
value={password}
onChange={onChange}
/>
</div>
<div className="form-group">
<input
type="password"
placeholder="Confirm Password"
name="password2"
value={password2}
onChange={onChange}
/>
</div>
<input type="submit" className="btn btn-primary" value="Register" />
</form>
<p className="my-1">
Already have an account? <Link to="/login">Sign In</Link>
</p>
</section>
);
};
Register.propTypes = {
setAlert: PropTypes.func.isRequired,
register: PropTypes.func.isRequired
};
export default connect( null, { setAlert , register })(Register);
and this is one of my actions auth.js where i request my api
import axios from "axios";
import { setAlert } from './alert'
import {
REGISTER_SUCCESS,
REGISTER_FAIL
} from './types'
//Register user
export const register = ( { name, email, password } ) => async dispatch => {
const config = {
headers: {
'Content-type': 'application/json'
}
}
const body = JSON.stringify({ name , email, password });
try {
const res = await axios.post('http://localhost:5000/api/users', body, config);
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
});
} catch (error) {
const errors = error.response.data.errors;
if(errors){
errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
}
dispatch({
type:REGISTER_FAIL
});
}
}
I am pretty sure this might be an axios error on how i am trying to perform a request or a redux mistake.
My app works fine, if i donĀ“t enter or enter invalid data to my registration form all my validation alerts show up. The issue is when i submit the form and try to send the data to register the new user.
This is my login page of my basic notes app ! in React JS.
I am using my own API when ever I am placing my email and password I except that we should get auth-token, In my response but ended up getting a error !
This is my login page component
import React, { useState } from 'react';
export default function Login() {
const [credentials, setcredentials] = useState({ email: ' ', password: '' });
const handleSubmit = async (e) => {
e.preventDefault();
const response = await fetch('http://localhost:5500/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: credentials.email,
password: credentials.password,
}),
});
const json = await response.json();
console.log(json);
};
const onchange = (e) => {
setcredentials({ ...credentials, [e.target.name]: [e.target.value] });
};
return (
<div>
<div className='container my-2'>
<form className='container my-2' onSubmit={handleSubmit}>
<div className='form-group my-2 '>
<label htmlFor='email'>Email address</label>
<input
type='email'
className='form-control'
id='email'
value={credentials.email}
name='email'
aria-describedby='emailHelp'
placeholder='Enter email'
onChange={onchange}
/>
<small id='emailHelp' className='form-text text-muted'>
We'll never share your email with anyone else.
</small>
</div>
<div className='form-group my-2'>
<label htmlFor='password'>Password</label>
<input
type='password'
className='form-control'
value={credentials.password}
name='password'
id='password'
placeholder='Password'
onChange={onchange}
/>
</div>
<button type='submit' className='btn btn-primary my-2'>
Submit
</button>
</form>
</div>
</div>
);
}
// Backend side code for the client side
router.post(
'/login',
[
body('email', 'Enter a valid email ').isEmail(),
body('password').isLength({ min: 5 }),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { email, password } = req.body;
try {
let user = await User.findOne({ email });
if (!user) {
return res
.status(400)
.json({ error: 'Please try to login with correct credentials' });
}
const passwordCompare = await bcrypt.compare(password, user.password); // returns promise
if (!passwordCompare) {
return res
.status(400)
.json({ error: 'Please try to login with correct credentials' });
}
const data = {
id: user._id,
};
const authtoken = jwt.sign(data, JWT_SECRET);
res.json({ authtoken });
} catch (error) {
console.log(error.message);
res.status(500).send('Internal Server Error');
}
}
);
The errors I am getting in console
In chrome developer tools it underline the fetch API ,
I am using the correct API only but still getting the same error
I am making a MERN application with register and login functionality. When i try to submit the form in the browser the console shows me a 400 bad request. The functionality works on the backend and returns a 200 ok status but not on the front-end.
this is a picture of the error in the browser.
here is my code below
validation
const Validator = require("validator");
const isEmpty = require("is-empty");
module.exports = function validateRegisterInput(data) {
let errors = {};
data.name = !isEmpty(data.name) ? data.name : "";
data.email = !isEmpty(data.email) ? data.email: "";
data.password = !isEmpty(data.password) ? data.password: "";
data.password2 = !isEmpty(data.password2) ? data.password2: "";
if(Validator.isEmpty(data.name)) {
errors.name = "Name field is Required";
}
if(Validator.isEmpty(data.email)) {
errors.email = "Email field is Required";
} else if(!Validator.isEmail(data.email)) {
errors.email = "Email is invalid"
}
if (Validator.isEmpty(data.password)) {
errors.password = "Password field is required";
}
if (Validator.isEmpty(data.password2)) {
errors.password2 = "Confirm password field is required";
}
if(!Validator.isLength(data.password, {min: 6, max: 30})){
errors: password = "Password must be at least 6 characters";
}
if(!Validator.equals(data.password, data.password2)){
errors.password2 = "Password must match"
}
return {
errors,
isValid: isEmpty(errors)
};
};
controller
const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require ("jsonwebtoken");
const keys = require("../../config/key");
const validateRegisterInput = require("../../validation/register");
const validateLoginInput = require("../../validation/login");
const User = require("../../models/User");
router.post("/register", (req, res) => {
//FORM VALIDATION
const {errors, isValid } = validateRegisterInput(req.body)
//CHECK VALIDATION
if(!isValid) {
return res.status(400).json(errors)
}
User.findOne({ email: req.body.email }).then( returnedUser => {
if(returnedUser) {
return res.status(400).json({email: "Email already exists"});
}
});
// saving user with request information to database
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
});
bcrypt.genSalt(10, (err, salt)=>{
bcrypt.hash(newUser.password, salt, (err, hash)=>{
if(err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => res.json(user))
.catch(err => console.log(err));
});
});
});
router.post("/login", (req, res)=>{
const {errors, isValid} = validateLoginInput(req.body)
if(!isValid){
return res.status(400).json(errors)
}
const email = req.body.email;
const password = req.body.password
User.findOne({ email: email }).then(user =>{
if(!user){
return res.status(404).json({ emailNotFound: "Email not found"});
}
bcrypt.compare(password, user.password).then(isMatch => {
if(isMatch){
const payload = { id: user.id, name: user.name };
jwt.sign(payload,
keys.secretOrKey,
{expiresIn: 31556926},
(err, token) => {
res.json({ success: true, token: "Bearer " + token });
});
} else {
return res.status(400)
.json({passwordincorrect: "password incorrect"})
}
})
})
});
module.exports = router;
Action
import axios from "axios";
import setAuthToken from "../utils/setAuthToken";
import jwt_decode from "jwt-decode";
import {
GET_ERRORS,
SET_CURRENT_USER,
USER_LOADING
} from "./types";
// Register User
export const registerUser = (userData, history) => dispatch => {
axios.post("/api/users/register", userData)
.then(res => history.push("/login")) // re-direct to login on successful register
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Login - get user token
export const loginUser = userData => dispatch => {
axios
.post("/api/users/login", userData)
.then(res => {
// Save to localStorage
// Set token to localStorage
const { token } = res.data;
localStorage.setItem("jwtToken", token);
// Set token to Auth header
setAuthToken(token);
// Decode token to get user data
const decoded = jwt_decode(token);
// Set current user
dispatch(setCurrentUser(decoded));
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
// Set logged in user
export const setCurrentUser = decoded => {
return {
type: SET_CURRENT_USER,
payload: decoded
};
};
// User loading
export const setUserLoading = () => {
return {
type: USER_LOADING
};
};
// Log user out
export const logoutUser = () => dispatch => {
// Remove token from local storage
localStorage.removeItem("jwtToken");
// Remove auth header for future requests
setAuthToken(false);
// Set current user to empty object {} which will set isAuthenticated to false
dispatch(setCurrentUser({}));
};
component
import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { registerUser } from "../../actions/authActions";
import classnames from "classnames";
class Register extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
password: "",
password2: "",
errors: {},
};
}
componentDidMount() {
// If logged in and user navigates to Register page, should redirect them to dashboard
if (this.props.auth.isAuthenticated) {
this.props.history.push("/dashboard");
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({
errors: nextProps.errors,
});
}
}
onChange = (e) => {
this.setState({ [e.target.id]: e.target.value });
};
onSubmit = (e) => {
e.preventDefault();
const newUser = {
name: this.state.name,
email: this.state.email,
password: this.state.password,
password2: this.state.password2,
};
console.log(newUser);
this.props.registerUser(newUser, this.props.history);
};
render() {
const { errors } = this.state;
return (
<div className="container">
<div className="row">
<div className="col s8 offset-s2">
<Link to="/" className="btn-flat waves-effect">
<i className="material-icons left">keyboard_backspace</i> Back to
home
</Link>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<h4>
<b>Register</b> below
</h4>
<p className="grey-text text-darken-1">
Already have an account? <Link to="/login">Log in</Link>
</p>
</div>
<form noValidate onSubmit={this.onSubmit}>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.name}
error={errors.name}
id="name"
type="text"
className={classnames("", {
invalid: errors.name
})}
/>
<label htmlFor="name">Name</label>
<span className="red-text">{errors.name}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.email}
error={errors.email}
id="email"
type="email"
className={classnames("", {
invalid: errors.email
})}
/>
<label htmlFor="email">Email</label>
<span className="red-text">{errors.email}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password}
error={errors.password}
id="password"
type="password"
className={classnames("", {
invalid: errors.password
})}
/>
<label htmlFor="password">Password</label>
<span className="red-text">{errors.password}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password2}
error={errors.password2}
id="password2"
type="password"
className={classnames("", {
invalid: errors.password2
})}
/>
<label htmlFor="password2">Confirm Password</label>
<span className="red-text">{errors.password2}</span>
</div>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<button
style={{
width: "150px",
borderRadius: "3px",
letterSpacing: "1.5px",
marginTop: "1rem",
}}
type="submit"
className="btn btn-large waves-effect waves-light hoverable blue accent-3"
>
Sign up
</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
Register.propTypes = {
registerUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
auth: state.auth,
errors: state.errors,
});
export default connect(mapStateToProps, { registerUser })(withRouter(Register));
Here is the root server
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const app = express();
const users = require("./controllers/api/users")
app.use(
bodyParser.urlencoded({
extended: false
})
);
//DATA BASE CONFIGURATION
const dbkeys = require("./config/key").mongoURI;
mongoose.connect(
dbkeys,
{useNewUrlParser: true} )
.then(()=> console.log("database connection successful"))
.catch(err => console.log(err))
app.use(passport.initialize());
require("./config/passport")(passport);
app.use("/api/users", users);
const port = 5000;
app.listen( port, () => console.log("server us up and running on port 5000!"))
Axios sends the data as JSON (application/json). You're currently only using the body parser for urlencoded, which refers to application/x-www-form-urlencoded which is the data format which <form>s use by default.
You need to also use bodyParser.json():
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
I am working on a project , first i did user signup and login based on jwt authentication * note i am using reactjs * i want to disallow users from logging in several time from different tabs or browsers , what shall i do ? how to implement such service and where? i will provide the whol code that may be helpful
i want some one to help me implement not just give me the logic
This is my main express file :
//the main framework , express
var express = require('express');
//path , used for joining pathes
var path = require('path');
//cross origin resource sharing
var cors= require('cors')
//body parser used to take data from forms , to be used later on
var bodyParser=require("body-parser");
//for security reasons , http security(not https)
var helmet= require('helmet')
//for parsing tokens and session cookies
var cookieParser= require('cookie-parser')
//assigning express functionaities as a global variable
const app = express()
//assigning cors functionaities as a global variable
app.use(cors())
//headers that will be sent to the browser
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Methods', ['PATCH', 'POST', 'GET', 'DELETE', 'PUT']);
res.setHeader('Access-Control-Allow-Headers' , '*')
res.setHeader('Access-Control-Expose-Headers' ,'content-type')
next();
});
//body parser for form data
app.use(bodyParser.json())
app.use(bodyParser.json({ type: 'application/json' }))
app.use(bodyParser.urlencoded({ extended: true }))
app.use(cookieParser())
// secure apps by setting various HTTP headers
app.use(helmet())
// enable CORS - Cross Origin Resource Sharing
app.options('*', cors());
//fetching index from react
app.use(express.static('./build/'));
app.use(express.static(path.join(__dirname, './client/build')));
app.get('*', (req, res) => {
res.send(express.static(path.join(__dirname, './client/build/index.html'))) ;
});
//giving the functionalities of users.js to a variable users to be used later on
var Users = require('./routes/Users')
//using the functions assigned for users
app.use('/users', Users)
//exporting the app file
module.exports = app
this is the routes file which contains my controller:
const express = require('express')
//setting a users variable to be used as a router instead of app post , get ..
const users = express.Router()
//cross oigin resource sharing
const cors = require('cors')
//jwt for user login authentication
const jwt = require('jsonwebtoken')
//bcrypt for password encryption and decryption
const bcrypt = require('bcrypt')
//using te user model
const User = require('../model/user')
//setting users as cros origin functionalities
users.use(cors())
//privat key or jwt encryption and decryption
process.env.SECRET_KEY = 'q1w2e3r4t5y6u7i8o9p0o9i8u7y6t5r4e3w2q1'
//main signup function , exported
users.post('/signup', (req, res) => {
//setting a new user object to be manipulated and inserted to db
//data taken from react client side
const today = new Date()
const userData = {
username : req.body.username,
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
password: req.body.password,
created: today
}
//a function from sequelize , a wrapper for later on functions
//searches if the username is found or not
User.findOne({
where: {
//searching in the whhole db for this user name
username: req.body.username
}
})
// encrypting the password using bcrypt encryption function
//bcrypt uses a hash function to encrypt the user given password
//will not reach this part if user is duplicated
.then(user => {
if (!user) {
//hashing the password , 10 is a number for permutations 2pwr10 = a certain string built in
bcrypt.hash(req.body.password, 10, (err, hash) => {
userData.password = hash
//creating a user with the given data
User.create(userData)
//send the username to the response tab in console
.then(user => {
res.json({ status: user.username + ' '+ 'Registered!' })
})
//any error will be consoled here
.catch(err => {
res.send('error: ' + err)
})
})
} else {
//will reach if username is found , User.findOne
res.json({ error: 'User already exists' })
}
})
.catch(err => {
res.send('error: ' + err)
})
})
//main login functionality
users.post('/login', (req, res) => {
///searches for username in db at first
User.findOne({
where: {
username: req.body.username
}
})
//if the user is found , it compared the password with the given password
//it compared it the encrypted pass in the db
//and decrypts it to compare
.then(user => {
if (user) {
//if user name is found the deryption starts here
if (bcrypt.compareSync(req.body.password, user.password)) {
//each user is given a certain jwt token for authentication
//jwt.sign , Synchronously sign the given payload into a JSON Web Token string payload
//secret key provided above
//token is assigned using the front end whuck sends it with the request
let token = jwt.sign(user.dataValues, process.env.SECRET_KEY, {
expiresIn: 1440
})
//send token to local storage of the browser that checks it
res.send(token)
}
} else {
//reaches here if user isnt found
res.status(400).json({ error: 'User does not exist' })
}
})
//catches any error from the above blocks
.catch(err => {
res.status(400).json({ error: err })
})
})
users.get('/profile', (req, res) => {
//Synchronously verify given token using a secret or a public key to get a decoded token token -
// JWT string to verify secretOrPublicKey - Either the secret for HMAC algorithms,
//or the PEM encoded public key for RSA and ECDSA.
// [options] - Options for the verification returns - The decoded token.
var decoded = jwt.verify(req.headers['authorization'], process.env.SECRET_KEY)
//searches for user
User.findOne({
//decode user id and jwt
where: {
id: decoded.id
}
})
//if true, user is sent as a json object to browser
.then(user => {
if (user) {
console.log(user)
res.json(user)
} else {
//if false , send this response
res.send('User does not exist')
}
})
.catch(err => {
res.send('error: ' + err)
})
})
module.exports = users
react front end end-points:
import axios from 'axios'
import jwt_decode from 'jwt-decode'
//the signup endpoint sent from front end and interpreted by the browser
//route is an api called users , exported from server side
//posting user data as in server
//sending a response if true
export const signup = newUser => {
return axios
.post('users/signup', {
username : newUser.username,
first_name: newUser.first_name,
last_name: newUser.last_name,
email: newUser.email,
password: newUser.password
})
.then(response => {
console.log('Registered')
})
}
//login end point
//using username and password , using the decoded id
export const login = async user => {
try {
const response = await axios
.post('users/login', {
username: user.username,
password: user.password
});
localStorage.setItem('usertoken', response.data);
return response.data;
}
catch (err) {
console.log(err);
}
}
Login react page
import React, { Component } from 'react'
import { withRouter} from 'react-router-dom';
import { login } from './api-user'
class Login extends Component {
constructor() {
super()
this.state = {
username: '',
password: '',
errors: {}
}
this.onChange = this.onChange.bind(this)
this.onSubmit = this.onSubmit.bind(this)
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value })
}
// parseJwt(token) {
// if (!token) { return; }
// const base64Url = token.split('.')[1];
// const base64 = base64Url.replace('-', '+').replace('_', '/');
// return JSON.parse(window.atob(base64));
// }
onSubmit(e) {
e.preventDefault()
const user = {
username:this.state.username,
password: this.state.password
}
login(user).then(res => {
if (res) {
this.props.history.push(`/profile`)
}
})
localStorage.setItem('username',
JSON.stringify(this.state.username))
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6 mt-5 mx-auto">
<form noValidate onSubmit={this.onSubmit}>
<h1 className="h3 mb-3 font-weight-normal">Please sign in</h1>
<div className="form-group">
<label htmlFor="text">Username</label>
<input
type="text"
className="form-control"
name="username"
placeholder="Enter username"
value={this.state.username}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
name="password"
placeholder="Password"
value={this.state.password}
onChange={this.onChange}
/>
</div>
<button
type="submit"
className="btn btn-lg btn-primary btn-block"
>
Sign in
</button>
</form>
</div>
</div>
</div>
)
}
}
signup react page
mport React, { Component } from 'react'
import { signup } from './api-user'
class SignUp extends Component {
constructor() {
super()
this.state = {
username:'',
first_name: '',
last_name: '',
email: '',
password: '',
errors: {}
}
this.onChange = this.onChange.bind(this)
this.onSubmit = this.onSubmit.bind(this)
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value })
}
onSubmit(e) {
e.preventDefault()
const newUser = {
username: this.state.username,
first_name: this.state.first_name,
last_name: this.state.last_name,
email: this.state.email,
password: this.state.password
}
signup(newUser).then(res => {
this.props.history.push(`/login`)
})
}
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-6 mt-5 mx-auto">
<form noValidate onSubmit={this.onSubmit}>
<h1 className="h3 mb-3 font-weight-normal">Register</h1>
<div className="form-group">
<label htmlFor="username">User Name</label>
<input
type="text"
className="form-control"
name="username"
placeholder="Enter your username"
value={this.state.username}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label htmlFor="first_name">First name</label>
<input
type="text"
className="form-control"
name="first_name"
placeholder="Enter your first name"
value={this.state.first_name}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label htmlFor="last_name">Last name</label>
<input
type="text"
className="form-control"
name="last_name"
placeholder="Enter your lastname name"
value={this.state.last_name}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label htmlFor="email">Email address</label>
<input
type="email"
className="form-control"
name="email"
placeholder="Enter email"
value={this.state.email}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
name="password"
placeholder="Password"
value={this.state.password}
onChange={this.onChange}
/>
</div>
<button
type="submit"
className="btn btn-lg btn-primary btn-block"
>
Register!
</button>
</form>
</div>
</div>
</div>
)
}
}
export default SignUp
please i asked this question before but no one helped me , some fellows gave me the logic but without the ode , i really in need of some code , what should i do ? new table to record signins ? how to connect my already found user table and if i want a new access_token table ? or should i do a flag in user table that changes (i dont know how , i just have the ideas )
From what I understand from your question is that you don't want your user to open the login page or the signup page if they are already signed in.
If thats the problem then a simple solution is to redirect the user to homepage/dashboard whenever they try to login if they are already authenticated.
<Route
exact path='/login'
render={props => this.state.isAuth ? <Redirect to='/dashboard' /> : <Login />}
/>
I'm trying to make a React-Node.js application for practice. I encountered an problem in sending POST request. When I fetch POST request in App.js, it returns only id. I expected it to return 3 more values.
Current object
{ _id: 5a046d52bb5d37063b3c8b21 }
Ideal object
{_id: "59e9fed60fe8bf0d7fd4ac6e", name: "recipe1", ingredients: "apple", descriptions: "cut an apple"}
How should I add values to req.body correctly? I referred this solution Post an object with fetch using react js and express API server but it didn't work with my app.
index.js (node.js)
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();
// Serve static files from the React app
app.use(express.static(path.join(__dirname, 'client/build')));
app.use(bodyParser.urlencoded({ extended: true}));
var db
const MongoClient = require('mongodb').MongoClient
MongoClient.connect
('mongodb://Recipe:recipebox#ds125914.mlab.com:25914/ayumi', (err, database) => {
if (err) return console.log(err)
db = database
app.listen(8080, () => {
console.log('listening on 8080')
})
})
app.get('/api', (req,res)=> {
db.collection('recipe').find().toArray((err, results) => {
if(err) return console.log("no recipe");
res.json(results);
})
})
app.post('/recipe', (req,res)=>{
db.collection('recipe').save(req.body, (err, result) => {
if(err) return console.log(err);
console.log(req.body)
console.log('save to database');
res.redirect('/');
})
})
App.js (react)
class App extends Component {
constructor(props){
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e){
e.preventDefault();
fetch('/recipe', {
method: 'POST',
body: JSON.stringify({
name: this.refs.name.value,
ingredients: this.refs.ingredients.value,
descriptions: this.refs.descriptions.value
}),
headers: {"Content-Type" : "application/json"}
})
.then((res)=> {
return res.json()
})
.then((body)=>{
console.log("body" + body)
console.log("result" + this.refs.name.value)
})
}
render() {
return (
<div className="App">
<h1>Recipe List</h1>
<form onSubmit={this.handleSubmit}>
<input type="text" placeholder="name" ref="name" />
<input type="text" placeholder="ingredients" ref="ingredients" />
<input type="text" placeholder="descriptions" ref="descriptions" />
<input type="submit"/>
</form>
</div>
)
}
}
export default App;
Server-side changes:
app.post('/recipe', (req, res) => {
// log the body of the request, to make sure data is properly passed
console.log(req.body);
// use mongodb's insertOne instead of the deprecated save
db.collection('recipe').insertOne(req.body, (err, result) => {
if (err) return console.log(err);
// log the result of db insertion
console.log(result);
console.log('saved to database');
// send the freshly saved record back to the front-end
res.json(result);
});
});
Front-end changes:
class App extends Component {
constructor(props){
super(props);
// add state to hold recipe returned from POST call
this.state = {
recipe: null,
name: '',
ingredients: '',
descriptions: ''
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const { name, ingredients, descriptions } = this.state;
fetch('/recipe', {
method: 'POST',
body: JSON.stringify({
name,
ingredients,
descriptions
}),
headers: {"Content-Type" : "application/json"}
})
// when call completes, it should return the newly created recipe object
// as it was saved in the DB - just store it into state
.then((recipe)=> {
this.setState({recipe});
});
// TODO: handle error case
}
render() {
// added a paragraph tag to display the ID of the freshly created recipe
// it's only displayed if recipe is not null or undefined
// further changes: turning inputs into controlled inputs
const { name, ingredients, descriptions } = this.state;
return (
<div className="App">
<h1>Recipe List</h1>
<form onSubmit={this.handleSubmit}>
<input
value={name}
type="text"
onChange={e => this.setState({ name: e.target.value })}
placeholder="name" />
<input
value={ingredients}
type="text"
onChange={e => this.setState({ ingredients: e.target.value })}
placeholder="ingredients" />
<input
value={descriptions}
type="text"
onChange={e => this.setState({ descriptions: e.target.value })}
placeholder="descriptions" />
<input type="submit"/>
{ recipe &&
<p>Saved ID: {this.state.recipe._id}</p>
}
</form>
</div>
);
}
}
export default App;
Further changes: turned all three text inputs into controlled inputs (values of all 3 fields are tracked in state, and passed to fetch when the form is submitted).