I'll try to give a premise and then follow it up with the code.
I decided to implement Material UI into my React project, and I got most of it going. How the app is set up, the user is faced with the Login page. The Login.js module renders the SignIn.js module, enters their credentials, and clicks submit. The formData, onChange and onSubmit are passed as props to the SignIn component from the Login component -- and the Login component receives these via mapStateToProps. The Login component uses the connect middleware to link redux state to the react app.
Clicking submit triggers the formData (in the Login component which are passed to the SignIn component) to hit my login method located in "../../actions/auth";. The error occurs from within this method, at the axios call in the try catch, where I attempt to communicate with the backend const response = await axios.post("/api/auth", body, config);
What's weird is that dispatch({ type: LOGIN_SUCCESS, payload: response.data }); never gets hit, which is supposed to set the state to the token returned from the backend, as it seems that LOGIN_SUCCESS is never executed. But what's VERY weird is that console logging the token actually works! It just seems as through it's never stored, forcing AUTH_ERROR to get invoked instead.
This is my Login component:
// Login.js
import SignIn from "../../material/SignIn";
const Login = ({ setAlert, login, isAuthenticated }) => {
const [formData, setFormData] = useState({
email: "",
password: ""
});
const { email, password } = formData;
const onChange = e => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const onSubmit = e => {
login(email, password);
};
// Redirect if logged in
if (isAuthenticated) {
return <Redirect to="/dashboard" />;
}
return (
<Fragment>
<SignIn
email={email}
password={password}
onSubmit={onSubmit}
onChange={onChange}
isAuthenticated={isAuthenticated}
/>
</Fragment>
);
};
Login.propTypes = {
setAlert: PropTypes.func.isRequired,
login: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(
mapStateToProps,
{ setAlert, login }
)(Login);
And the SignIn component that it is rendering is here:
// SignIn.js
export default function SignIn({ email, password, onChange, onSubmit }) {
const classes = useStyles();
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form onSubmit={e => onSubmit(e)} className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
onChange={e => onChange(e)}
fullWidth
id="email"
label="Email Address"
name="email"
value={email}
// autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
onChange={e => onChange(e)}
fullWidth
name="password"
label="Password"
type="password"
value={password}
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={5}>
<MadeWithLove />
</Box>
</Container>
);
}
Clicking the submit button raises the onSubmit method in my Login component:
// Login user
export const login = (email, password) => async dispatch => {
// Config needed because we're sending data
const config = {
headers: {
"Content-Type": "application/json"
}
};
const body = JSON.stringify({ email, password });
try {
const response = await axios.post("/api/auth", body, config);
// Skips over this dispatch
dispatch({
type: LOGIN_SUCCESS,
payload: response.data
});
// But hits this dispatch.. and then console logs 'REACHED' as seen below
dispatch(loadUser());
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach(error => {
dispatch(setAlert(error.msg, "danger"));
});
}
dispatch({
type: LOGIN_FAIL
});
}
};
If you notice, after the axios call, loadUser is called, defined as:
// Load user
export const loadUser = () => async dispatch => {
const token = localStorage.token;
console.log('REACHED!'); // reached
if (token) {
setAuthToken(token);
}
try {
const response = await axios.get("/api/auth");
dispatch({
type: USER_LOADED,
payload: response.data
});
} catch (err) {
dispatch({
type: AUTH_ERROR // This is dispatched
});
}
};
The backend route is the following:
// #route POST api/auth
// #desc Authenticate user and get token
// #access Public
router.post(
"/",
[
check("email", "Please include a valid email").isEmail(),
check("password", "Please is required").exists()
],
async (req, res) => {
const errors = validationResult(req);
// send back any errors
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
const { email, password } = req.body;
try {
// check if user exists, send error if so
let user = await User.findOne({ email });
if (!user) {
return res
.status(400)
.json({ errors: [{ msg: "Invalid credentials" }] });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res
.status(400)
.json({ errors: [{ msg: "Invalid credentials" }] });
}
// return jsonwebtoken so that way they're logged in right
// away, without having to log in after registering
const payload = {
user: {
id: user.id
}
};
jwt.sign(
payload,
config.get("jwtSecret"),
{
expiresIn: process.env.PORT ? 3600 : 36000
},
(err, token) => {
if (err) throw err;
console.log(token); // prints token!
return res.json({ token });
}
);
} catch (err) {
console.log(err);
res.status(500).send("Server error");
}
}
);
I'm so confused at this point. The token is being rendered but it seems as though React doesn't 'await' the response before Node gets a chance to send it back.
Not sure how to explain this, but I solved it by getting rid of the onSubmit trigger from the form tag and placing it on the in SignIn.js. I changed the type of the button to type button as well. Got it working :)
Related
I want to use my own API to check the information about email and password, but I don't know how to do that. Anything information that I put show up "Login" but I need to just show up "Login" if the information was the same that I registered in my database.
import { useState } from 'react';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import { Link } from "react-router-dom"
const Login = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const handleSubmit = (e) => {
e.preventDefault()
const info = {email, password}
fetch('http://localhost:3333/login/', {
mode: 'no-cors',
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify(info)
}).then((response) => {
console.log(response)
console.log("login")
}).catch(() => {
console.log("NO")
})
}
return (
<div className="all ">
<div className='button d-flex justify-content-center '>
<Link to="/" className="text-center btn btn-secondary btn-lg m-4">Login</Link>
<Link to="/register" className="text-center btn btn-secondary btn-lg m-4">Register</Link>
</div>
<p className='text-center'>Sign With:</p>
<div className="container d-flex justify-content-center">
<Form onSubmit={handleSubmit}>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" value = {email} onChange={(e) => setEmail (e.target.value)} placeholder="Enter email" required/>
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control type="password" value = {password} onChange={e => setPassword(e.target.value)} placeholder="Password" />
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Check me out" />
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
</div>
</div>
);
}
export default Login;
My API is shown below and it's working fine and the login function is verifying well
const {
PrismaClient
} = require("#prisma/client");
const prisma = new PrismaClient();
const bcrypt = require('bcrypt');
module.exports = {
async createUser(req, res) {
try {
const {
firstName,
lastName,
email,
password,
age,
role
} = req.body
const salt = await bcrypt.genSalt();
console.log(salt)
const hash = await bcrypt.hash(password, salt)
console.log(hash)
const verifyemail = await prisma.UserInfo.findUnique({
where: {
email
}
})
if (verifyemail) {
return res.json({
error: "there is a email with the same name, please change."
})
}
const user = await prisma.UserInfo.create({
data: {
firstName: firstName,
lastName: lastName,
email: email,
password: hash,
age: age,
role: role
}
});
return res.json(user)
} catch (error) {
return res.json({
error
})
}
},
async login(req, res) {
try {
const {email, password} = req.body
const user = await prisma.UserInfo.findUnique({
where: {
email : req.body.email
}
})
if(user) {
const match = await bcrypt.compare(password, user.password)
if(match) {
return res.send("login")
}
else {
return res.send("There is something wrong with your password")
}
}
} catch (error) {
return res.json({
error
})
}
}
}
What I have understood from your question is that, no matter what username and password you are entering you are always ending up in the .then block, while if the username/password is wrong it should go to the catch block.
If I have understood that correctly, I would suggest updating your node code to handle this scenario. Fetch will only go in catch if there is a network error or CORS error, check this
With this, I would suggest you can add an else block in your Node code and add
return res.status(401).send("Icorrect password");
after this, in front end code, you can add
.then(response => /* check response status code and throw 'Incorrect' if 401 */ )
I am having an issue with my React Redux and Node app. I am trying to Log in an existing user but in my console i am getting the following error:
Uncaught (in promise) TypeError: error.response.data is undefined
The console points to the following block of code:
export const login = (email, password) => async (dispatch) => {
const body = { email, password };
try {
const res = await axios.post('http://localhost:5000/api/auth', body);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch(loadUSer());
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach((error) => dispatch(setAlert(error.msg, 'danger')));
}
dispatch({
type: LOGIN_FAIL
});
}
};
This is my server side for user auth auth.js:
const express = require('express');
const router = express.Router();
const User = require('../../models/User');
const auth = require('../../middleware/auth');
const config = require('config');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { check , validationResult } = require('express-validator/');
//#route GET api/auth
//#desc Test route
//#access public
router.get('/',auth, async(req, res)=> {
try{
const user = await User.findById(req.user.id).select('-password');
res.json(user);
}catch(err){
console.error(err.message);
res.status(500).send('Server Error');
}
});
//#route POST api/auth
//#desc Authenticate user & get token
//#access public
router.post('/', [
check('email', 'Plese include a valid email').isEmail(),
check('password', 'Password is required').exists()
],
async (req, res)=> {
const errors = validationResult(req);
if(!errors.isEmpty()){
return res.status(400).json({ errors:errors.array()}); //400 is for bad requests
}
const { email, password } = req.body;
try{
//See if user exists
let user = await User.findOne({ email });
if(!user){
return res.status(400).json({ errors: [{ msg:'Invalid credentials' }] });
}
//Compare the input password, plane text, to the encrypted password.
const isMatch = await bcrypt.compare(password, user.password);
if(!isMatch){
return res.status(400).json({ errors: [{ msg:'Invalid credentials' }] });
}
//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;
And this is my Login component:
import React, { Fragment, useState } from 'react'
/* import axios, { Axios } from 'axios'; */
import { Link, Navigate } from 'react-router-dom'
import { connect } from 'react-redux';
import { PropTypes } from 'prop-types';
import { login } from '../../actions/auth';
const Login = ({ login, isAuthenticated }) => {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const { email, password } = formData;
const onChange = e => setFormData({
...formData, [e.target.name]:e.target.value
});
const onSubmit = async e => {
e.preventDefault();
login(email, password);
}
//Redirect if logged in
if(isAuthenticated){
return <Navigate to="/dashboard"/>;
}
return (
<Fragment>
<section className='container'>
<h1 className="large text-primary">Sign Up</h1>
<p className="lead"><i className="fas fa-user"></i> Sign Into Your Account</p>
<form className="form" action="create-profile.html" onSubmit={e => onSubmit(e)}>
<div className="form-group">
<input type="email"
placeholder="Email Address"
name="email" value={email}
onChange={e => onChange(e)}
required/>
</div>
<div className="form-group">
<input
type="password"
placeholder="Password"
name="password"
minLength="6"
value={password}
onChange={e => onChange(e)}
required
/>
</div>
<input type="submit" className="btn btn-primary" value="Login" />
</form>
<p className="my-1">
Don´t have an account? <Link to="/register">Sign up</Link>
</p>
</section>
</Fragment>
)
}
Login.propTypes = {
login: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
}
const mappedStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
})
export default connect(mappedStateToProps , { login })(Login)
For some reason there are sometimes i am able to login and sometimes i encounter this issue but i cannot figure out what am i doing wrong.
My redux devtools also show the AUTH_ERROR action type:
This is my auth.js in my actions directory.
export const loadUSer = () => async dispatch => {
if(localStorage.token){
setAuthToken(localStorage.token);
}
try {
const res = await axios.get('http://localhost:5000/api/auth');
dispatch({
type: USER_LOADED,
payload: res.data
})
} catch (error) {
dispatch({
type:AUTH_ERROR
})
}
}
auth.js (reducers directory):
import{
REGISTER_FAIL,
REGISTER_SUCCESS,
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
LOGOUT
} from '../actions/types'
const initialState = {
token: localStorage.getItem('token'),
isAuthenticated: null,
loading: true,
user: null
}
function authReducer(state = initialState, action){
const { type, payload } = action
switch (type) {
case USER_LOADED:
return {
...state,
isAuthenticated:true,
loading: false,
user:payload
}
case LOGIN_SUCCESS:
case REGISTER_SUCCESS:
localStorage.setItem('token', payload.token);
return {
...state,
...payload,
isAuthenticated: true,
loading: false
}
case LOGOUT:
case LOGIN_FAIL:
case REGISTER_FAIL:
case AUTH_ERROR:
localStorage.removeItem('token');
return {
...state,
toke: null,
isAuthenticated: false,
loading: false
}
default:
return state;
}
}
export default authReducer
So i first log in with an user everything works fine, i logout and log in with a different user and also works, i now logout and want to login to the first user again and the error shows up. The only difference between both users is that one has a profile and the other one doesn´t.
When i try to log in with the user with no profile my app crashes and my vscode terminal shows a different errors:
Can't set headers after they are sent to the client
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
When I using axios post error pesistenly comes out. I also installed cors. I have no idea why this happening. Here is my react code.
import React, { useState } from 'react'
import { Link } from 'react-router-dom'
import axios from 'axios'
export default function Login() {
const [Email, SetEmail] = useState('')
const [Password, SetPassword] = useState('')
return (
<div>
<h1>Login</h1>
<input type="text" placeholder="Email" value={Email} onChange={(e) => SetEmail(e.target.value)} />
<input type="password" placeholder="Password" value={Password} onChange={(e) => SetPassword(e.target.value)} />
<button type="submit" onClick={(e) => {
const config = {
headers: {
'Content-Type': 'application/json'
}
}
const body = JSON.stringify({ Email, Password })
axios.post('http://localhost:4000/app/signin', body, config)
.then((response) => console.log(response.data))
}}>Login</button>
<div style={{ float: "right", marginTop: "10px" }}>
<Link to="/signup" style={{ color: "white" }}>
SIGN UP
</Link>
</div>
</div>
)
}
I'm practicing login. I didn't use form tag. Because when I submit data to backend, the console initialized and can't see what's happening. Next is my node.js code.
router.post(
'/signin',
[
check('email', 'Type proper e-mail').isEmail(),
check('password', 'Password is required').not().isEmpty()
],
async (request, response) => {
try{
const {email, password} = request.body;
let user = await signUpTemplateCopy.findOne({email});
const errors = validationResult(request);
if (!errors.isEmpty()) {
return response.status(401).json({errors: errors.array()});
}
if (!user){
return response.status(401).json({ msg: "There is no user with this e-mail"});
}
let isPasswordMatch = await bcryptjs.compare(password, user.password);
if (isPasswordMatch) {
const payload = {
user: {
id : user.id
}
}
jwt.sign(
payload,
config.get('jwtSecret'),
(err, token) => {
if (err) throw err;
response.json({token});
}
)
} else return response.status(401).json({msg: "wrong password"});
} catch (error) {
console.log(error.msg);
return response.status(500).json({msg: "Server Error..."});
}
})
I can't guess even what's the problem is. Please save me from this problem.
For validating email and password I would recommend the express-validator library. You would implement it like so:
router.post(
"/signin",
[
body("email").isEmail().withMessage("Email must be valid"),
body("password")
.trim()
.notEmpty()
.withMessage("You must supply a password"),
]
You are probably going to need an error handling middleware. The signupTemplateCopy seems like a confusing naming convention to what should be your User model, but you would take that instead and run an if conditional on it like so:
async (req, res) => {
const { email, password } = req.body;
const existingUser = await User.findOne({ email });
if (!existingUser) {
throw new BadRequestError("Invalid Credentials");
}
I use a little known npm library for that BadRequestError() you see above called #dc_microurb/common#^1.0.7. Also, instead of bcrypt, you may also want to give scrypt a try from the crypto library, but what you have will work.
I am also not sure about how you are generating a JWT. Let's say you were doing it as I suggest with, const existingUser = await User.findOne({ email }); or in your case, const existingUser = await signUpTemplateCopy.findOne({ email });, then you would take that existingUser or in your case user to generate the JWT like so:
const userJwt = jwt.sign(
{
id: existingUser.id,
email: existingUser.email,
},
process.env.JWT_KEY!
);
Then you need to store that JWT in a session object which I do not see anywhere in your code, like so:
req.session = {
jwt: userJwt,
};
and then you can finally send back res.status(200).send(user); or in my example, res.status(200).send(existingUser);
I am using react-redux, axios, and JWT to create a registration system to a simple web app I built. No matter what is entered, I get a "Please enter all fields error". I have programmed other errors, and even when all input is valid I get the same one. I do not see any compilation error either in dev tools or in my terminal. This is my first try at authentication/registration.
This is my registerModal:
class RegisterModal extends Component{
state = {
Modal: false,
name: '',
email: '',
password:'',
msg: null
}
static propTypes ={
isAuthenticated: PropTypes.bool,
error: PropTypes.object.isRequired,
register: PropTypes.func.isRequired,
clearErrors: PropTypes.func.isRequired
}
componentDidUpdate(prevProps){
const {error} = this.props;
if(error !== prevProps.error){
//reg error
if(error.id === 'REGISTER_FAIL'){
this.setState({msg: error.msg.msg})
}else{
this.setState({msg: null});
}
}
}
toggle = () =>{
this.props.clearErrors();
this.setState({
Modal: !this.state.Modal
});
}
onChange = (e)=>{
this.setState(
{[e.target.name]: e.target.value}
);
}
onSubmit = e =>{
e.preventDefault();
const{name, email, password} = this.state;
//create user object
const newUser = {
name,
email,
password
};
this.props.register(newUser);
}
render(){
return(
<div>
<NavLink onClick = {this.toggle} href ="#" color = "danger">
Register
</NavLink>
<Modal
isOpen={this.state.Modal}
toggle={this.toggle} >
<ModalHeader toggle={this.toggle}>Register</ModalHeader>
<ModalBody>
{this.state.msg ? <Alert color = "danger">{this.state. msg}</Alert>: null}
<Form onSubmit = {this.onSubmit}>
<FormGroup>
<Label for ="name">Name</Label>
<Input
type = "text"
name= "name"
id = "name"
placeholder="Name"
onChange = {this.onChange}>
</Input>
</FormGroup>
<FormGroup>
<Label for ="Email">Email </Label>
<Input
type = "email"
name= "email"
id = 'email'
placeholder="Enter email"
onChange = {this.onChange}>
</Input>
</FormGroup>
<FormGroup>
<Label for ="Password">Password</Label>
<Input
type = "password"
name= "password"
id = "password"
placeholder="Password"
onChange = {this.onChange}>
</Input>
</FormGroup>
<Button
color="success"
style={{marginTop:'2rem'}}
block>
Register</Button>
</Form>
</ModalBody>
</Modal>
</div>
);
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.auth.isAuthenticated,
error: state.error
});
export default connect(
mapStateToProps,
{register, clearErrors})(RegisterModal);
This is in my auth.js file in routes folder:
//POST api/auth
//#desc Auth user
router.post('/', (req, res)=> {
const { email, password } = req.body;
//validation
if(!email || !password){
return res.status(400).json({msg: 'Please enter all fields'});
}
//Check for existing user
User.findOne({email})
.then(user =>{
if(!user) return res.status(400).json({msg: 'User does not exists'})
//Validate password
bcrypt.compare(password, user.password)
.then(isMatch =>{
if(!isMatch) return res.status(400).json({ msg: 'Invalid credentials'});
jwt.sign(
{id: user.id},
config.get('jwtSecret'),
{expiresIn: 3600},
(err, token) => {
if(err) throw err;
res.json({
token,
user: {
id: user.id,
name: user.name,
email: user.email
}
});
}
)
})
});
});
authActions.js:
//check tokens and register user
export const loadUser = () => (dispatch, getState) => {
//user loading
dispatch({type: USER_LOADING});
axios.get('/api/auth/user', tokenConfig(getState))
.then(res => dispatch({
type: USER_LOADED,
payload: res.data
}))
.catch(err => {
dispatch(returnErrors(err.response.data, err.response.status));
dispatch({
type: AUTH_ERROR
});
});
}
export const register = ({name, email, password}) => dispatch =>{
//headers
const config = {
header: {
'Content-Type': 'application/json'
}
}
//request body
const body = JSON.stringify({name, email, password});
axios.post('/api/users', body, config)
.then(res => dispatch({
type: REGISTER_SUCCESS,
payload:res.data
}))
.catch(err=>{
dispatch(returnErrors(err.response.data, err.response.status, 'REGISTER_FAIL'));
dispatch({
type: REGISTER_FAIL
})
})
}
//setup config /header and token
export const tokenConfig = getState => {
//get token from local storage
const token = getState().auth.token;
//headers
const config = {
headers: {
"Content-type": "application/json"
}
}
//if token add to headers
if(token){
config.headers['x-auth-token'] = token;}
return config;
}
Please let me know if I should add anything.
Assuming your registration route handles the request correctly, changing "header" to "headers" in the config you are passing into the axios.post() of your register action should solve it.