context api state changes but doesn't reflects untill refreshes browser - reactjs

I am updating state and storing token in local storage.
After clicking the login button the state changes but doesn't go the dashboard page until I refresh the browser tab.
Why it is not automatically detecting state and updating it?
Logic: If the token is available in local storage it should redirect it to the dashboard. otherwise, the login page should appear and after authentication should redirect to the dashboard.
Below are the user context and Login page
UserContext
import React, { createContext, Component } from 'react';
import { Redirect } from 'react-router-dom';
export const UserContext = createContext();
class UserContextProvider extends Component {
state = {
isLoading: false,
isAuthenticated: false,
token: null,
UserName: null,
Email: null,
Role: null
}
auth = (auth, profile) => {
this.setState = ({
isAuthenticated: auth,
}, () => { });
if (profile) {
localStorage.setItem("token", profile.token);
this.setState = ({
token: profile.token
}, () => { });
} else {
this.setState = ({
token: null,
UserName: null,
Email: null,
Role: null
});
}
}
isLoading = load => {
this.setState({ isLoading: load })
}
logout = () => {
localStorage.removeItem("token")
this.setState({
isAuthenticated: false,
token: null,
UserName: null,
Email: null,
Role: null
})
}
componentDidMount = async () => {
if (localStorage.getItem("token")) {
const base64Url = localStorage.getItem("token").split('.')[1];
const base64 = base64Url.replace('-', '+').replace('_', '/');
var tokenData = (JSON.parse(window.atob(base64)));
await this.setState({
isAuthenticated: true,
token: localStorage.getItem("token"),
UserName: tokenData.name,
Email: tokenData.email,
Role: tokenData.role
});
}
return <Redirect to="/login" />
}
render() {
return (
<UserContext.Provider value={{ ...this.state, auth: this.auth, isLoading: this.isLoading, profileData: this.profileData, logout: this.logout }}>
{this.props.children}
</UserContext.Provider>
);
}
}
export default UserContextProvider;
Login.jsx
const Login = () => {
const { auth, profileData, token, isAuthenticated } = useContext(UserContext);
const [email, setemail] = useState('');
const [password, setpassword] = useState('');
const [error, setError] = useState(null)
const handlesubmit = (e) => {
e.preventDefault();
const user = {
Email: email,
Password: password,
}
axios.post("http://localhost:2000/user/", user)
.then(res => {
if (res.data.error) {
setError(res.data.msg);
auth(res.data.valid, null);
} else if (res.data.valid) {
setError(null);
auth(res.data.valid, res.data)
}
}).catch(error => {
console.log(error)
});
}
return (
<div>
{console.log(isAuthenticated, token)}
{isAuthenticated ? <Redirect to='/dashboard' /> : <Redirect to='/login' />}
<div className="container mt-5">
<div className="col-md-6 mx-auto text-center">
<div className="header-title">
<h1 className="wv-heading--title">
Login Here!
</h1>
</div>
</div>
<div className="row mt-5">
<div className="col-4 mx-auto">
<div className="myform form ">
<form onSubmit={handlesubmit}>
<div className="form-group">
<input type="email" name="email" value={email} onChange={(e) => { setemail(e.target.value) }} className="form-control" id="email" placeholder="Email" required />
</div>
<div className="form-group">
<input type="password" value={password} name="password" onChange={(e) => { setpassword(e.target.value) }} id="password" className="form-control" placeholder="Password" required />
</div>
{
error ?
<div className="mt-3 mb-3">
<p style={{ color: "red", fontSize: "8" }}> <b>Error :</b> {error}</p>
</div>
:
null
}
<div className="text-center ">
<button type="submit" className="btn btn-outline-info">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
)
}
export default Login;

I got it.
There was a mistake in setState in user context auth function.

Related

How to not give user access to the login page when they are already logged in?

https://pastebin.com/mXgqRP4j
I am trying to implement that when a user is logged in, the user has no access to the login page. To do that I have put an if condition at the end that if the user is authenticated, the user will be redirected to the dashboard even when they input the path to the login component. But whats happening is that when I input the link to the login page (I have routes set up), the login page shows up for a split second and then disappears and then the dashboard appears. What should have happened was that the user shouldve been redirected directly to the dashboard. Please guide me!
import { useEffect, useState } from "react"
import Admin from "../../pages/Admin"
import { Navigate } from "react-router-dom";
import { useNavigate } from "react-router-dom";
function AdminLogin() {
const navigate = useNavigate()
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [csrf, setCsrf] = useState('')
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
function getCsrf(){
fetch("http://localhost:8000/csrf/", {
credentials: "include",
})
.then((res) => {
let csrfToken = res.headers.get("X-CSRFToken");
setCsrf({csrf: csrfToken});
})
.catch((err) => {
console.log(err);
})
}
const login = (event) => {
event.preventDefault();
fetch("http://localhost:8000/login/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": csrf.csrf,
},
credentials: "include",
body: JSON.stringify({username: username, password: password}),
})
.then(isResponseOk)
.then((data) => {
console.log(data);
setIsAuthenticated(true)
localStorage.setItem("authenticated", true);
setUsername('')
setPassword('')
// this.setState({isAuthenticated: true, username: "", password: ""});
})
.catch((err) => {
console.log('inside login catch')
console.log(csrf.csrf, 'catch')
console.log(err);
});
}
const isResponseOk = (response) =>{
if (response.status >= 200 && response.status <= 299) {
return response.json();
} else {
console.log(response)
throw Error(response.statusText);
}
}
useEffect(() => {
//getSessions
fetch("http://localhost:8000/session/", {
credentials: "include",
})
.then((res) => res.json())
.then((data) => {
// console.log(data);
if (data.isAuthenticated) {
setIsAuthenticated(true)
console.log(data)
} else {
setIsAuthenticated(false)
console.log(data)
getCsrf()
}})
.catch((err) => {
console.log(err);
});
}, [])
console.log(csrf);
console.log(counter)
const handleUsername = (e) => {
setUsername(e.target.value)
}
const handlePassword = (e) => {
setPassword(e.target.value)
}
const loginScreen = (
<div className="login-box m-auto">
<div className="card">
<div className="card-body login-card-body">
<p className="login-box-msg">Sign in to start your session</p>
<form method="post" onSubmit={login}>
<div className="input-group mb-3">
<input required type="text" value={username} onChange={handleUsername} className="form-control" placeholder="Username" />
<div className="input-group-append">
<div className="input-group-text">
<span className="fas fa-envelope" />
</div>
</div>
</div>
<div className="input-group mb-3">
<input required type="password" value={password} onChange={handlePassword} className="form-control" placeholder="Password" />
<div className="input-group-append">
<div className="input-group-text">
<span className="fas fa-lock" />
</div>
</div>
</div>
<div className="row">
<div className="col-4">
<button type="submit" className="btn btn-primary btn-block">Sign In</button>
</div>
</div>
</form>
</div>
</div>
</div>)
if(isAuthenticated)
{
return <Navigate replace to="/admin/dashboard" />;
}
else{
return loginScreen
}
}
You can create isLoading state alongside isAuthenticated state and initialize it with true and show the loading screen until checking authentication is finished and set isLoading to false. After that you can show the login screen only if isLoading is false and isAuthentcated is also false.
If it's okay to use Redux so I suggest using Redux-Persist and make it rehydrate the auth part so you will not face this issue.

Login is not a function after logging out then trying to log back in

I am building a react project where I want to implement a log-in/ log out screen.
I am able to succesfully log in but once I log out, I cannot log back in with the error "TypeError
Login is not a function" being displayed. It seems to be coming from LogInForm.js, from the Login(details); line. I cannot spot my mistake here so I would greatly appreciate any feedback. Cheers.
LogInForm.js
import React, { useState } from "react";
function LogInForm({ Login, error }) {
const [details, setDetails] = useState({ email: "", password: "" });
const submitHandler = (e) => {
e.preventDefault();
Login(details);
};
return (
<form onSubmit={submitHandler}>
<div className="form-inner">
<h2>Login</h2>
{/* ERROR!*/}
<div className="form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
name="email"
id="email"
onChange={(e) => setDetails({ ...details, email: e.target.value })}
value={details.email}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password:</label>
<input
type="password"
name="password"
id="password"
onChange={(e) =>
setDetails({ ...details, password: e.target.value })
}
value={details.password}
/>
</div>
<input type="submit" value="Log In" />
</div>
</form>
);
}
export default LogInForm;
LogIn.js
import React, { useState } from "react";
import App from "./App";
import LogInForm from "./LogInForm";
function LogIn() {
const adminUser = {
email: "admin#admin.com",
password: "test123"
};
const [user, setUser] = useState({ name: "", email: "" });
const [error, setError] = useState("");
const Login = (details) => {
if (
details.email == adminUser.email &&
details.password == adminUser.password
) {
console.log("Logged in!");
setUser({ email: details.email, password: details.password });
} else {
console.log("details dont match");
}
};
const Logout = () => {
console.log("Logout");
};
return (
<div className="Display">
{user.email != "" ? (
<App email={user.email} password={user.password} />
) : (
<LogInForm Login={Login} error={error} />
)}
</div>
);
}
export default LogIn;
index.js
import React from "react";
import ReactDOM from "react-dom";
import LogIn from "./LogIn";
ReactDOM.render(<LogIn />, document.getElementById("root"));
App.js
import React from "react";
import LogIn from "./LogIn";
import LogInForm from "./LogInForm";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
email: this.props.email,
password: this.props.password,
};
this.logOut = this.logOut.bind(this);
}
logOut() {
console.log("Logged out");
this.setState({ email: "", password: "" });
}
componentDidMount() {
console.log("Email:" + this.state.email);
console.log("Password:" + this.state.password);
}
render() {
if (this.state.email == "") {
return <LogInForm />;
} else {
{
console.log(this.state);
}
return (
<div>Hello</div>,
<button onClick={this.logOut}>Log Out</button>
);
}
}
}
export default App;
The issue is haven't passed Login function in App file. This could be done in a more simple way, like this.
function LogInForm({ handleLogin, user, setUser }) {
return (
<form onSubmit={handleLogin}>
<div className="form-inner">
<h2>Login</h2>
{/* ERROR!*/}
<div className="form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
name="email"
id="email"
onChange={(e) => setUser({ ...user, email: e.target.value })}
value={user.email}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password:</label>
<input
type="password"
name="password"
id="password"
onChange={(e) => setUser({ ...user, password: e.target.value })}
value={user.password}
/>
</div>
<input type="submit" value="Log In" />
</div>
</form>
);
}
const adminUser = {
email: "admin#admin.com",
password: "test123"
};
export default function App() {
const [user, setUser] = useState({ name: "", email: "" });
const [isAuthenticated, setIsAuthenticated] = useState(false);
const handleLogin = () => {
if (
user.email === adminUser.email &&
user.password === adminUser.password
) {
console.log("Logged in!");
setIsAuthenticated(true);
} else {
console.log("details dont match");
}
};
const handleLogout = () => {
setIsAuthenticated(false);
console.log("Logout");
};
return (
<div className="Display">
{isAuthenticated ? (
<button onClick={handleLogout}>logout</button>
) : (
<LogInForm
handleLogin={handleLogin}
user={user}
setUser={setUser}
/>
)}
</div>
);
}

Redirection to dashboard after login in react

I have a login page, and I want to redirect users to dashboard after the details are filled.
I have tried using history.push and redirect components but I couldn't redirect.
Login Page
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default Login;
I want to redirect to other page once the form is submitted with the email and password.
I've been trying this for days but I couldn't find a solution.
import { withRouter } from 'react-router';
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
this.props.history.push("/dashboard");
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default withRouter(Login);
have some complain about your code.
first: for form validation and handling you dont need to use state,
there is a library called Formik which will help you a lot with
this.
second: if you are using redux to check user is logged in or
not you need to create a private route for routes which cannot be
accessible for public like here dashboard component.
third: to use history you need to wrap your
component inside withRouter HOC which will pass route props to your
component so you can use history or if your are using functional component you can use useHistory() hook.

PropType declared function, value is undefined

I'm trying to declare my function from a Action to the PropType but it always display a "...value is undefined". can someone tell where's my error?
I'v tried repack my react folder which is "client" using "npx" and also every related solution.
action/auth.js
import {
LOGIN_SUCCESS,
LOGIN_ERROR,
USER_LOADING,
USER_LOADED,
REGISTER_ERROR,
REGISTER_SUCCESS
} from "./types";
import axios from "axios";
export const getConfig = getState => {
let config = {
headers: { "Content-Type": "application/json" }
};
const token = getState().auth.token;
if (token) {
config.headers["x-auth-token"] = `Bearer ${token}`;
}
return config;
};
export const registerUser = userObj => (dispatch, getState) => {
axios
.post("/auth/register", JSON.stringify(userObj), getConfig(getState))
.then(result => {
console.log(result);
dispatch({
type: LOGIN_SUCCESS,
payload: result.data
});
})
.catch(error => {
console.log(error);
dispatch({
type: LOGIN_ERROR
});
});
};
component/main/RegisterForm
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Alert } from "reactstrap";
import { registerUser } from "../../actions/auth";
import { connect } from "react-redux";
import PropTypes from "prop-types";
export class RegisterForm extends Component {
constructor(props) {
super(props);
document.title = "OnlineChat - Register";
}
state = {
firstname: "",
lastname: "",
email: "",
password: "",
password1: "",
error: null,
visible: false
};
static propTypes = {
registerUser: PropTypes.func.isRequired
};
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
onDismiss = e => {
this.setState({ visible: false, error: null });
};
onSubmit = e => {
e.preventDefault();
const { firstname, lastname, email, password, password1 } = this.state;
const userObj = this.state;
console.log(firstname, lastname, email, password, password1);
if (!firstname || !lastname || !email || !password || !password1) {
return this.setState({ error: "Please fill all fields.", visible: true });
}
if (password !== password1) {
return this.setState({ error: "Password must match.", visible: true });
}
this.props.registerUser(userObj);
this.setState({
firstname: "",
lastname: "",
email: "",
password: "",
password1: ""
});
};
render() {
const {
firstname,
lastname,
email,
password,
password1,
error,
visible
} = this.state;
return (
<div className="d-flex align-items-center" style={{ height: "100vh" }}>
<div className="container">
<div className="row">
<div className="col-12 col-sm-12 col-md-6 col-lg-6 offset-md-3">
<Alert color="danger" isOpen={visible} toggle={this.onDismiss}>
<strong>Alert! </strong>
{error}
</Alert>
<div className="card">
<div className="card-body">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label htmlFor="">First Name</label>
<input
type="text"
autoComplete="off"
className="form-control"
onChange={this.onChange}
value={firstname}
name="firstname"
/>
</div>
<div className="form-group">
<label htmlFor="">Last Name</label>
<input
type="text"
autoComplete="off"
className="form-control"
onChange={this.onChange}
value={lastname}
name="lastname"
/>
</div>
<div className="form-group">
<label htmlFor="">Email</label>
<input
type="email"
autoComplete="off"
className="form-control"
onChange={this.onChange}
value={email}
name="email"
/>
</div>
<div className="form-group">
<label htmlFor="">Password</label>
<input
type="password"
autoComplete="off"
className="form-control"
onChange={this.onChange}
value={password}
name="password"
/>
</div>
<div className="form-group">
<label htmlFor="">Re-type Password</label>
<input
type="password"
autoComplete="off"
className="form-control"
onChange={this.onChange}
value={password1}
name="password1"
/>
</div>
<button
className="btn btn-block btn-outline-success"
type="submit"
>
Register
</button>
</form>
<div className="d-block justify-content-left pt-2">
<Link to="/" className="cLink">
Have an account ?
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(
mapStateToProps,
{ registerUser }
)(RegisterForm);
reducer/authReducer
import {
LOGIN_ERROR,
LOGIN_SUCCESS,
REGISTER_ERROR,
REGISTER_SUCCESS,
USER_LOADING
} from "../actions/types";
const initialState = {
token: localStorage.getItem("token"),
isAuthenticated: null,
isLoading: false,
user: null
};
export default (state = initialState, action) => {
switch (action.type) {
case USER_LOADING:
return {
...state,
isLoading: true
};
case LOGIN_SUCCESS:
case REGISTER_SUCCESS:
localStorage.setItem("token", action.payload.token);
return {
...state,
...action.payload,
isAuthenticated: true,
isLoading: false
};
case LOGIN_ERROR:
case REGISTER_ERROR:
return {
...state,
token: null,
isAuthenticated: null,
isLoading: false,
user: null
};
default:
return state;
}
};
Here's the error message keeps prompting in my console.
Error Message
Delete export from class, make it class RegisterForm extends Component { not export class RegisterForm extends Component { since you are exporting the module at the bottom saying export default connect

How to fix "XML Parsing Error: syntax error" in React JS?

I am trying to setup user login/auth in MERN stack. When I fill the register form and submit I get the following message on console.
XML Parsing Error: syntax error
Location: http://localhost:3000/api/users/register
Line Number 1, Column 1:
I have tested my api using Postman and everything seems to be working fine.
Below is my api for register requuest:
// API routes
// #routes POST api/users/register
// #access Public
// #route POST api/users/register
// #desc Register user
// #access Public
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(user => {
if (user) {
return res.status(400).json({ email: "Email already exists" });
} else {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
// Hash password before saving in database
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));
});
});
}
});
});
On the client side:
Register.jsx
import ...
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
};
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));
I cannot see what is wrong in the code. I have followed a tutorial and done the exact same thing.
My registerUser method is in the following file.
authActions.js
// 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({}));
};

Resources