Node.js React JWT Login - node.js

It's ok, I got my Token on Node.js, I tested with Postman.
But I want to recuperate my Token in React with localStorage.
I don't understand why, but it doesn't work.
Browser toolbox says "TypeError: this is undefined".
When I try with "bind", browser say nothing. No error but
my localStorage is empty.
For the second case, PreventDefault() doesn't work, i replaced it by persist().
Login.js
class Login extends Component {
state = {
email:"",
password:"",
}
async postLogin(e){
await this.setState({
[e.target.name]: e.target.value
})
e.preventDefault(e);
const login = {
email:this.state.email,
password:this.state.password
};
await axios.post("http://localhost:7777/api/users/login", login)
.then((response) => {
const {token} = response.data;
localStorage.setItem("token", token)
this.props.history.push("/articles")
})
.catch((error) => {
console.log(error);
})
}
render(){
return(
<div className="containerSign">
<h1>Connecte toi</h1>
<form onSubmit={this.postLogin}>
<input className="inputFormSign" type="email" placeholder="Email"/>
<input className="inputFormSign" type="password" placeholder="Mot de passe"/>
<button className="btnFormSign" type="submit">Envoyer</button>
</form>
</div>
)
}
}
export default Login;
Login.js with bind
postLogin = this.postLogin.bind(this);
async postLogin(e){
await this.setState({
[e.target.name]: e.target.value
})
e.persist(e);
const login = {
email:this.state.email,
password:this.state.password
};
await axios.post("http://localhost:7777/api/users/login", login)
.then((response) => {
const {token} = response.data;
localStorage.setItem("token", token)
this.props.history.push("/articles")
})
.catch((error) => {
console.log(error);
})
}
render(){
return(
<div className="containerSign">
<h1>Connecte toi</h1>
<form onSubmit={this.postLogin}>
<input className="inputFormSign" type="email" placeholder="Email"/>
<input className="inputFormSign" type="password" placeholder="Mot de passe"/>
<button className="btnFormSign" type="submit">Envoyer</button>
</form>
</div>
)
}
}
export default Login;

You should use autobind decorator package to eradicate this issue!
Installation:
npm install --save autobind-decorator
Examples:
import autobind from 'autobind-decorator';
#autobind
class Component { }
// or
#autobind
method() {
return this.value
}
note:
To use ES7 decorators you must install babel-plugin-transform-decorators

You must bind the method, for example using class property:
async postLogin = (e) => {
...
}

Related

axios.get not working while am i searching product name

backend
const ProductListFilter = async (req, res) => {
try {
const productList = await productModel.find(req.query).collation({ locale: "en", strength: 2 });
return res
.status(201)
.send({
status: true,
message: `Total ${productList.length} product found `,
data: productList,
});
} catch (error) {
res.status(500).send({ status: false, message: error.message });
}
};
frontend
import axios from "axios";
import { useState } from "react";
const ProductListFilter = () => {
const [search, setSearch] = useState();
const handleChange = (e) => {
setSearch({ ...search, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
await axios
.get(`http://localhost:5000/ProductListFilter`)
.then((res) => alert(res.data.message))
.catch((err) => console.log(err.response.data.message));
};
console.log(search);
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="search">
<input type="search" name="search" id="search" onChange={handleChange} />
<button type="submit">Submit</button>
</label>
</form>
</div>
);
};
export default ProductListFilter;
you need to add name in query param as shown below.
import axios from "axios";
import { useState } from "react";
const ProductListFilter = () => {
const [search, setSearch] = useState();
const handleChange = (e) => {
setSearch({ ...search, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
await axios
.get(`http://localhost:5000/ProductListFilter?name=${search.name}`)
.then((res) => alert(res.data.message))
.catch((err) => console.log(err.response.data.message));
};
console.log(search);
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="search">
<input type="search" name="search" id="search" onChange={handleChange} />
<button type="submit">Submit</button>
</label>
</form>
</div>
);
};
export default ProductListFilter;

How to display error message on the mern app

I'm trying to display an error message when a user tries to sign in with an unregistered user but I'm not able to get that error message on the frontend(reactjs) that I am sending from my backend(nodejs, express, MongoDB).
I am using redux to handle the state of the react app.
user login form onSubmit code:
const onSubmit = (data) => {
if (isLogin) {
dispatch(signin(data, history));
} else {
dispatch(signup(data, history));
}
};
actions creators for auth
import * as api from "../api";
export const signin = (formData, history) => async (dispatch) => {
try {
// login the user
const { data } = await api.signIn(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log(error);
dispatch({ type: "ERROR", data: error.response.data.message });
}
};
export const signup = (formData, history) => async (dispatch) => {
try {
// sign up the user
const { data } = await api.signUp(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log(error);
}
};
reducers for auth:
const authReducer = (state = { authData: null }, action) => {
switch (action.type) {
case "AUTH":
localStorage.setItem("profile", JSON.stringify({ ...action?.data }));
return { state, authData: action?.data };
case "LOGOUT":
localStorage.clear();
return { state, authData: null };
case "ERROR":
return { state, authData: action?.data };
default:
return state;
}
};
export default authReducer;
Backend sign in code
const signin = async (req, res) => {
const { email, password } = req.body;
try {
const existingUser = await User.findOne({ email });
if (!existingUser)
return res.status(404).json({ message: "User doesn't exist." });
const isPasswordCorrect = await bcrypt.compare(
password,
existingUser.password
);
if (!isPasswordCorrect)
res.status(404).json({ message: "Invalid Credentials" });
const token = jwt.sign(
{ email: existingUser.email, id: existingUser._id },
"test",
{ expiresIn: "1h" }
);
res.status(200).json({ result: existingUser, token });
} catch (error) {
res.status(500).json({ message: "Something went wrong" });
}
};
sign API
import axios from "axios";
const API = axios.create({
baseURL: process.env.REACT_APP_BASE_URL,
});
export const signIn = (formData) => API.post("/user/signin", formData);
export const signUp = (formData) => API.post("/user/signup", formData);
Anyone, please help me with this.
Screenshots of the error response in Postman:
I just debugged the issue. First install redux-devtools-extension by npm install --save redux-devtools-extension
Then apply this in store(index.js file in your case) as follows
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import App from "./App";
import { reducers } from "./reducers";
import { composeWithDevTools } from "redux-devtools-extension";
const middleware = [thunk];
const store = createStore(
reducers,
composeWithDevTools(applyMiddleware(...middleware))
);
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
And now you can use the error message anywhere as follows (your Auth.js file)
import React, { useState } from "react";
import { useSelector } from "react-redux";
import Input from "../utils/Input";
import Label from "../utils/Label";
import { useForm, FormProvider } from "react-hook-form";
import { GoogleLogin } from "react-google-login";
import { useDispatch } from "react-redux";
import { useHistory } from "react-router";
import { signin, signup } from "../../actions/auth";
const Auth = () => {
const [isLogin, setIsLogin] = useState(true);
const formMethods = useForm();
const auth = useSelector((state) => state.auth);
const { authData } = auth;
const { handleSubmit } = formMethods;
console.log(authData);
const dispatch = useDispatch();
const history = useHistory();
const changeScreen = () => {
setIsLogin(false);
dispatch({ type: "LOGOUT" });
};
const onSubmit = (data) => {
if (isLogin) {
dispatch(signin(data, history));
} else {
dispatch(signup(data, history));
}
};
const googleSuccess = async (res) => {
const result = res?.profileObj;
const token = res?.tokenId;
try {
dispatch({ type: "AUTH", data: { result, token } });
history.push("/");
} catch (error) {
console.log(error);
}
};
const googleFailure = (error) => {
console.log(error);
console.log("Google sign in was unsuccessful");
};
return (
<section className="col-start-1 col-end-2 md:col-start-2 md:col-end-3 row-start-2 row-end-3 md:row-start-1 md:row-end-2 mx-3 sm:mx-0 md:my-auto">
<div className=" w-full max-w-md bg-primaryOne px-6 py-8 rounded-md shadow-md mx-auto">
<FormProvider {...formMethods}>
<form className="" onSubmit={handleSubmit(onSubmit)}>
<div className="w-full flex justify-around mb-2">
<button
className={`${
isLogin
? "bg-secondaryTwo"
: "transition bg-transparent hover:bg-secondaryTwo"
} text-white text-xs font-bold px-6 py-4 rounded-full`}
type="button"
onClick={() => setIsLogin(true)}
>
LOG IN
</button>
<button
className={`${
!isLogin
? "bg-secondaryTwo"
: "transition bg-transparent hover:bg-secondaryTwo"
} text-white text-xs font-bold px-6 py-4 rounded-full`}
type="button"
onClick={() => changeScreen()}
>
SIGN UP
</button>
</div>
<div>
{!isLogin && (
<div>
<Label labelName="Name" />
<Input inputName="name" type="text" bgColor="primaryTwo" />
</div>
)}
<div>
<Label labelName="Email" />
<Input inputName="email" type="email" bgColor="primaryTwo" />
</div>
<div>
<Label labelName="Password" />
<Input
inputName="password"
type="password"
bgColor="primaryTwo"
/>
</div>
</div>
<div className="text-center">
<button
type="button"
onClick={() => setIsLogin(!isLogin)}
className="text-neutral font-extralight text-xs pt-6"
>
{authData && <h1 style={{ color: "red" }}>{authData}</h1>}
{!isLogin
? "Already have an account? Log In"
: "Don't have an account? Sign Up"}
</button>
</div>
<button className="bg-secondaryTwo hover:bg-secondaryOne transition px-4 py-3 w-full rounded-md text-white font-bold mt-4 shadow-md">
{isLogin ? "Log In" : "Sign Up"}
</button>
<div className="flex items-center py-6">
<div className="w-1/2 h-px bg-white bg-opacity-40"></div>
<p className="text-white px-1 text-xs">OR</p>
<div className="w-1/2 h-px bg-white bg-opacity-40"></div>
</div>
<div>
<GoogleLogin
clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}
onSuccess={googleSuccess}
onFailure={googleFailure}
cookiePolicy="single_host_origin"
render={(renderProps) => (
<button
className="bg-blue-600 hover:bg-blue-500 transition px-4 py-3 w-full rounded-md text-white font-bold mb-4 shadow-md"
type="button"
onClick={renderProps.onClick}
disabled={renderProps.disabled}
>
<i className="fab fa-google mr-2"></i>Continue with Google
</button>
)}
/>
</div>
</form>
</FormProvider>
</div>
</section>
);
};
export default Auth;
And one last thing. Check nested object before using its properties like error.response.data.message (your auth.js actions file)
import * as api from "../api";
export const signin = (formData, history) => async (dispatch) => {
try {
// login the user
const { data } = await api.signIn(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log("An error occured while ");
const errMsg =
error.response && error.response.data.message
? error.response.data.message
: error.message;
dispatch({ type: "ERROR", data: errMsg });
console.log(errMsg);
}
};
export const signup = (formData, history) => async (dispatch) => {
try {
// sign up the user
const { data } = await api.signUp(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log(error);
}
};
Hope it helps!
As far as I understood, everything is working fine, and actually, there is no error happening on the frontend side. You have to check the status code of "await api.signIn(formData);" response. If it is 200, it means that everything is ok otherwise you have to check the message in the response to get the message error. As on the frontend there is thrown error to be catched.
you can aslo use react-toastify . you can get status code and response message from error and store it in state object in reducers/auth.js and access it using useSelector() then create if else conditions according to status code and pass message to toast(#error_message#).
just see react-toastify and know how to use it.

How do I implement login functionality in a MERN app?

I am developing a (simple-to-use) note-taking web application on my localhost (port 3000 for frontend, port 5000 for the backend). I'm having trouble implementing the user login functionality. I'll try to distill the problem here.
My main App.jsx component has a LoginScreen.jsx component as a child, which is here:
import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import AuthService from '../services/auth.js';
import './LoginScreen.css';
const LoginScreen = ({ history }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
useEffect(() => {
if (localStorage.getItem('authToken')) history.push('/');
}, [history]);
const loginHandler = async e => {
e.preventDefault();
try {
const data = { email, password };
AuthService.loginUser(data).then(response => {
localStorage.setItem('authToken', response.data.token);
});
history.push('/');
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError('');
}, 5000);
}
};
return (
<div className="login-screen">
<form
className="login-screen__form"
onSubmit={loginHandler}
autoComplete="off"
>
<h3 className="login-screen__title">Login</h3>
{error && <span className="error-message">{error}</span>}
<div className="form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
required
id="email"
placeholder="enter email"
value={email}
onChange={e => setEmail(e.target.value)}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{' '}
<Link
to="/forgotpassword"
className="login-screen__forgotpassword"
tabIndex={4}
>
Forgot Password?
</Link>
</label>
<input
type="password"
required
id="password"
placeholder="enter password"
value={password}
onChange={e => setPassword(e.target.value)}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary" tabIndex={3}>
Login
</button>
<span className="login-screen__subtext">
Don't have an account? <Link to="/register">Register</Link>
</span>
</form>
</div>
);
};
export default LoginScreen;
When the user clicks "Login," that should trigger the AuthService, shown here:
import http from '../routing/http-auth.js';
class AuthService {
loginUser = data => http.post('/login', data);
registerUser = data => http.post('/register', data);
userForgotPassword = data => http.post('/forgotpassword', data);
userPasswordReset = data => http.put('/passwordreset/:resetToken', data);
}
export default new AuthService();
The http in the above file is an axios instance, shown below.
import axios from 'axios';
export default axios.create({
baseURL: 'http://localhost:5000/api/v1/auth',
headers: {
'Content-type': 'application/json'
}
});
So, the request is routed to the backend, where it goes here:
import express from 'express';
import AuthController from './auth.controller.js';
const router = express.Router();
router.route('/register').post(AuthController.register);
router.route('/login').post(AuthController.login);
router.route('/forgotpassword').post(AuthController.forgotPassword);
router.route('/passwordreset/:resetToken').put(AuthController.passwordReset);
export default router;
And then here:
static login = async (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
if (!email || !password) {
return next(
new ErrorResponse('please provide an email and password', 400)
);
}
try {
const user = await User.findOne({ email }).select('+password');
if (!user) return next(new ErrorResponse('invalid credentials', 401));
const isMatch = await user.matchPasswords(password);
if (!isMatch) return next(new ErrorResponse('invalid credentials', 401));
sendToken(user, 200, res);
} catch (error) {
next(error);
}
};
This all worked on a dummy application, but now, it's not working in my note-taking app. I get the error:
Uncaught (in promise) TypeError: Cannot read property 'data' of undefined
at loginHandler (LoginScreen.jsx:27)
How can I make this work?
Your TypeError: Cannot read property 'data' of undefined means that your code tried to read the .data property from a undefined (null, missing) object.
At line 27 your code does setError(error.response.data.error); Therefore your error message means error exists but error.response does not.
Put console.log(error) right before that line 27 (or set a breakpoint) so you can make sure you understand the error object you catch.
It would be nice if the error message said TypeError: Cannot read property 'data' of an undefined object named error.response. But it doesn't so you must make that inference yourself.

How to send User to Next Page After form validation in react?

This in My SignUp Component, Im trying To send User to Signin Component If Username And Password Is correct.
this is Signup Code Below,
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import Axios from 'axios';
const initianValue = {
username: '',
password: '',
nameError: '',
passError: '',
dataError: '',
};
class SignUp extends Component {
constructor(props) {
super(props);
this.state = initianValue;
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleInputChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
validForm() {
let nameError = '';
let passError = '';
let dataError = '';
const user = {
username: this.state.username,
password: this.state.password,
};
if (!this.state.username) {
nameError = 'Enter Name';
}
if (user.username !== '' && user.password !== '') {
Axios.post('http://localhost:9000/checkUser', user)
.then((res) => this.setState({ dataError: res.data }))
.catch((err) => console.log(err));
}
if (!this.state.password) {
passError = 'Enter Password';
}
if (nameError || passError || dataError) {
this.setState({
nameError,
passError,
dataError,
});
return false;
}
return true;
}
handleSubmit = (e) => {
e.preventDefault();
const isvalid = this.validForm();
if (isvalid) {
this.setState(initianValue, () => this.props.history.push('/SignIn'));
}
};
render() {
return (
<div className='Main'>
<span className='create'>Create Account</span>
<div className='SignUp'>
<form onSubmit={this.handleSubmit}>
<div className='form-group'>
<label>Username</label>
<input
type='text'
name='username'
value={this.state.username}
className='form-control'
onChange={this.handleInputChange}
/>
<div className='error'>
{this.state.nameError}
{this.state.dataError}
</div>
<br />
<label>Password</label>
<input
type='password'
name='password'
value={this.state.password}
className='form-control'
onChange={this.handleInputChange}
/>
<div className='error'>{this.state.passError}</div>
<br />
<button type='submit' className='btn btn-primary'>
Sign Up
</button>
</div>
</form>
</div>
<div className='signinForm'>
<label>
Already Have Account <Link to='/Signin'> Sign In </Link>
</label>
</div>
</div>
);
}
}
export default SignUp;
Its Works Perfect If I Put Right username and password but in wrong username / password its also send me to Signin Page and Shows warning in console like this
index.js:1 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
in SignUp (created by Context.Consumer)
i wrap Both Component SignUp And Signin In Router,
this is my server.js file to send data if username and password is correct in database
app.post('/checkUser', function (req, res) {
const name = req.body.username;
const pass = req.body.password;
conn.query(
`SELECT * FROM users WHERE username = (?) AND password = (?) `,
[name, pass],
(err, rows) => {
if (err) throw err;
if (!rows.length) {
res.send('Wrong Data');
}
}
);
});
Your validForm makes an async call. By the time the async call is finished the validForm function as well as handleSubmit function execution is already completed. Then the then block is executed where you are setting state and therefore the error.
Solution: Make validForm an async function and await for your async call. Also make handleSubmit function an async and await for validForm.
Working demo
Code snippet
class SignUp extends Component {
constructor(props) {
super(props);
this.state = initianValue;
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleInputChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
async validForm() {
let nameError = "";
let passError = "";
let dataError = "";
const user = {
username: this.state.username,
password: this.state.password
};
if (!this.state.username) {
nameError = "Enter Name";
}
if (user.username !== "" && user.password !== "") {
await Axios.get("https://jsonplaceholder.typicode.com/todos/1", user) //fake api
.then(res => {
dataError = "user already exists"; //provide dynamic error..
//this.setState({ dataError: res.data }); // not required
})
.catch(err => console.log("err", err));
}
if (!this.state.password) {
passError = "Enter Password";
}
if (nameError || passError || dataError) {
this.setState({
nameError,
passError,
dataError
});
return false;
}
return true;
}
handleSubmit = async e => {
e.preventDefault();
const isvalid = await this.validForm();
if (isvalid) {
this.setState(initianValue, () => this.props.history.push("/SignIn"));
}
};
render() {
return (
<div className="Main">
<span className="create">Create Account</span>
<div className="SignUp">
<form onSubmit={this.handleSubmit}>
<div className="form-group">
<label>Username</label>
<input
type="text"
name="username"
value={this.state.username}
className="form-control"
onChange={this.handleInputChange}
/>
<div className="error">
{this.state.nameError}
{this.state.dataError}
</div>
<br />
<label>Password</label>
<input
type="password"
name="password"
value={this.state.password}
className="form-control"
onChange={this.handleInputChange}
/>
<div className="error">{this.state.passError}</div>
<br />
<button type="submit" className="btn btn-primary">
Sign Up
</button>
</div>
</form>
</div>
<div className="signinForm">
<label>
Already Have Account <Link to="/Signin"> Sign In </Link>
</label>
</div>
</div>
);
}
}
The issue could be on the handling of the response of the fetch. This is just a quick guess but try to not set the state of dataError and just modify the value of your variable dataError that you declared in this local function instead of the class variable. Does that make sense? when you check in your "if (nameError || passError || dataError)" you are checking for the local variable of your function and not the class which I think is fine but you aren't changing the variable if the response is an error.
Second if you change the setState and then check the state.dataError you might not get the updated value refresh yet in the function.
Let me know if that makes sense and if it works.

React : LocalStorage with a non-null value always

Hello I am using localStorage to save my jwt token from my api
But it is saving my token even if I close shut down the node server and etc.
and I would need to do a login check
here is my server route
app.route('/login')
.post(async (req,res)=>{
try {
const response = await usersControllers.signin(req.body);
const login = response.login;
console.log(login);
if(login.id && login.isValid){
const payload = {id: login.id};
res.json({
token: jwt.sign({data:payload}, app.config.jwt.secret,{expiresIn: '60'}),
response
});
}else{
console.log('entrou here');
res.sendStatus(HttpStatus.UNAUTHORIZED);
}
} catch (error) {
console.log('entrou here');
console.error(error.message);
res.sendStatus(HttpStatus.UNAUTHORIZED);
}
})
and in my front end react
i have this in my login:
import React, { Component } from 'react';
import {Form,FormGroup, Label, Input, Button, Alert} from 'reactstrap';
import Header from '../../components/header';
export default class Login extends Component {
constructor(props) {
super(props)
console.log(this.props);
this.state = {
message: this.props.location.state?this.props.location.state.message: '',
};
}
signIn = () => {
const data = {login:this.login,password:this.password};
const requestInfo = {
method:'POST',
body: JSON.stringify({data}),
headers: new Headers({
'Content-Type': 'application/json'
}),
};
fetch('http://localhost:9000/login', requestInfo)
.then(response => {
if(response.ok){
return response.json();
}
throw new Error("Login Invalido..")
})
.then(token => {
localStorage.setItem('token', token.token);
this.props.history.push("/users");
return;
})
.catch(e => {
this.setState({message: e.message})
});
}
render(){
return(
<div className="col-md-6">
<Header title="ReactJS Login"/>
<hr className="my-3"/>
{
this.state.message !== ''? (
<Alert color="danger" className ="text-center"> {this.state.message}</Alert>
) : ''
}
<Form>
<FormGroup>
<Label for="login">Login</Label>
<Input type="text" id="login" onChange={e => this.login = e.target.value } placeholder="Informe seu login" />
</FormGroup>
<FormGroup>
<Label for="password">Senha</Label>
<Input type="text" id="password" onChange={e => this.password = e.target.value } placeholder="Informe sua senha"/>
</FormGroup>
<Button color="primary" onClick={this.signIn}> Entrar </Button>
</Form>
</div>
);
}
}
here i set my jwt in localstorage:
.then(token => {
localStorage.setItem('token', token.token);
this.props.history.push("/users");
return;
})
in my other js file
my auth about jwt
const isAuth = () => {
console.log(localStorage.getItem('token'));
if(localStorage.getItem('token') !== null) {
console.log("entrou aq2");
return true;
}
return false;
};
in console.log(localStorage.getItem('token')); have value !== all time
Even without logging in with my api
The reason your
localStorage.getItem('token') !== null
is returning true is because you are using localStorage. localStorage's values does not expire therefore your value is stored in your localStorage until you call
localStorage.removeItem('token')
If you want your token be deleted after each time you close your browser, use sessionStorage instead. You can read more about authenticating with SPA here
Use JSON.stringify() to save in localstorage
.then(token => {
localStorage.setItem('token', JSON.stringify(token.token));
this.props.history.push("/users");
return;
})
and use JSON.parse() to get from localstorage
const isAuth = () => {
if(JSON.parse(localStorage.getItem('token')) !== null) {
console.log("entrou aq2");
return true;
}
return false;
};

Resources