Removing the token from local Storage - javascript

So here I have Login functionality via local storage token. I am getting the token upon user being created in The dev tools/Application. It is redirecting me to the home as it should. The thing that is not working is this. When I try to press the logout I am getting ×TypeError: Cannot read property 'push' of undefined it is showing the error in the Logout Handler function
Context Api
import React from "react";
import { useHistory } from "react-router-dom"
const UserContext = React.createContext();
function getUserFromLocalStorage() {
return localStorage.getItem("authToken")
? JSON.parse(localStorage.getItem("authToken"))
: { username: null, token: null };
}
function UserProvider({ children }) {
const [user, setUser] = React.useState(getUserFromLocalStorage());
const history = useHistory()
const logoutHandler = () =>{
localStorage.removeItem("authToken");
setUser(user);
history.push("/")
}
return (
<UserContext.Provider
value={{ user, setUser, logoutHandler }}
>
{children}
</UserContext.Provider>
);
}
export { UserContext, UserProvider };
Login Link
import React from "react";
import { Link } from "react-router-dom";
import { UserContext } from "../../context/user";
import { useHistory } from "react-router-dom"
export default function LoginLink() {
const { user, logoutHandler } = React.useContext(UserContext);
if (user.authToken) {
return (
<button
onClick={() => {
logoutHandler();
}}
className="login-btn"
>
logout
</button>
);
}
return <Link to="/login">login</Link>;
Header
import React from 'react';
import { Link, useHistory } from "react-router-dom";
import Search from './Search';
import './Header.css'
import SearchBooks from './SearchBooks';
import LoginLink from '../Signin/LoginLink';
import CartLink from '../Cart/CartLink';
import { UserContext } from '../../context/user';
const Header = () => {
const { user } = React.useContext(UserContext);
return (
<div className='header__container'>
<Link to='/'>
<img src='/audi.png' />
</Link>
<li>
<LoginLink />
</li>
{user.authToken &&(
<CartLink />
)
}
</div>
)
}
export default Header
Login
import { useState, } from "react";
import { useHistory } from "react-router-dom"
import axios from "axios";
import { Link } from "react-router-dom";
import "./Signin.css";
const Login = () => {
const { user, setUser } = React.useContext(UserContext);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const history = useHistory()
const loginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/login",
{ email, password },
config
);
localStorage.setItem("authToken", data.token);
setUser(user)
history.push("/");
} catch (error) {
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="login-screen">
<form onSubmit={loginHandler} className="login-screen__form">
<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="Email address"
onChange={(e) => setEmail(e.target.value)}
value={email}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{" "}
<Link to="/forgotpassword" className="login-screen__forgotpassword">
Forgot Password?
</Link>
</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary">
Login
</button>
<span className="login-screen__subtext">
Don't have an account? <Link to="/register">Register</Link>
</span>
</form>
</div>
);
};
export default Login;

Related

react context doesn't save authContext

EDIT: Just saw that the post was very long so sorry and thanks a lot to whom can help me.
I'm using react as front in a project and I have a problem that I couldn't solve and didn't find anything on the internet.
So the problem is that I'm using jwt for login and when I log in on my page it's like it removes the state by himself, I'll show you:
(by the way I just started so there is no css)
login page:
logged in:
Then if I refresh the page or do anything like click on a button it will come back to the initial state like I never logged in and throw me to the login page because it doesn't see me logged in.
Here is the code:
authProvider.js:
import { createContext, useState } from "react";
const AuthContext = createContext({});
export const AuthProvider = ({ children }) => {
const [auth, setAuth] = useState(null);
console.log(auth);
return (
<AuthContext.Provider value={{ auth, setAuth }}>
{children}
</AuthContext.Provider>
)
}
export default AuthContext;
useAuth.js:
import { useContext } from "react";
import AuthContext from "../context/authProvider";
const useAuth = () => useContext(AuthContext);
export default useAuth;
login.js:
import React, { useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import useAuth from '../../hooks/useAuth';
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { auth, setAuth } = useAuth();
const navigate = useNavigate();
const location = useLocation();
const from = location.state?.from?.pathname || '/';
const handleSubmit = (e) => {
e.preventDefault();
fetch('http://localhost:4000/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
password: password
})
}).then(res => res.json())
.then(data => {
if (data.message) {
document.querySelector('#error').innerHTML = data.message;
}
setAuth({ email, password, token: data.token, refreshToken: data.refreshToken, role: data.role });
console.log(auth);
navigate(from, { replace: true });
});
}
return (
<>
<h1>Login</h1>
<span id='error'></span>
<form onSubmit={handleSubmit}>
<label>Email</label>
<input id="email" type="email" required onChange={(e) => { setEmail(e.target.value) }} />
<label>Password</label>
<input id="password" type="password" required onChange={(e) => { setPassword(e.target.value) }} />
<button type='submit'>se connecter</button>
</form>
</>
);
};
export default Login;
the image for the logs:
and nav.js just so you know how I know it works but state doesn't stay:
import { Link } from 'react-router-dom';
import useAuth from '../hooks/useAuth';
const Nav = () => {
const { auth } = useAuth();
return (
<>
<nav>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
{
!auth ?
<>
<li>
<Link to="/login">Login</Link>
</li>
<li>
<Link to="/signup">Signup</Link>
</li>
</>
: null
}
{
auth?.role === 'user' ?
<li>
<Link to="/profile">Profile</Link>
</li>
: null
}
{
auth?.role === 'admin' ?
<li>
<Link to="/admin">Admin</Link>
</li>
: null
}
</ul>
</div>
</nav>
</>
)
}
export default Nav;
I don't know if you need more but just say me if needed.

nextjs firebaseauth redirect before render page if logged in

I have a login page and an auth provider as follow
import * as yup from "yup";
import { useState } from 'react'
import { AuthErrorCodes } from 'firebase/auth'
import Cover from '../../components/Cover'
import Head from 'next/head'
import Headingblock from '../../components/Headingblock'
import Section from '../../components/Section'
import { authErrorCodesTranslation } from '../../config/firebase';
import { siteTitle } from '../_app'
import { useForm } from 'react-hook-form';
import { yupResolver } from '#hookform/resolvers/yup';
import { useRouter } from 'next/router';
import { useAuth } from "../../contexts/auth";
import { auth } from '../../config/firebase';
import { signInWithEmailAndPassword } from "firebase/auth";
import {useEffect} from 'react'
export default function Login() {
const [response, setResponse] = useState({});
const [user, userLoading] = useAuth();
const router = useRouter();
console.log(userLoading);
if (!userLoading && user)
router.push('/');
const schema = yup.object().shape({
email: yup.string().email('Adresse email invalide').required('Veuillez renseigner votre adresse email.'),
password: yup.string().required('Veuillez renseigner votre mot de passe')
});
const { register, handleSubmit, formState } = useForm({
resolver: yupResolver(schema),
});
const { errors } = formState;
const onSubmit = async (data) => {
await signInWithEmailAndPassword(auth, data.email, data.password)
.then(userCredential => {
router.push("/profile");
}).catch(error => {
const authErrorCode = Object.keys(AuthErrorCodes).find(k => AuthErrorCodes[k] === error.message);
let errorTranslation = authErrorCodesTranslation.GLOBAL_AUTH_ERROR;
if (authErrorCode !== undefined)
errorTranslation = authErrorCodesTranslation[authErrorCode];
setResponse({ status: 'error', message: errorTranslation });
})
}
return (
<>
<Head>
<title>{siteTitle} - Connexion</title>
</Head>
<Cover />
<Section>
<div className='container marginNTop100'>
<div style={{ padding: '3rem 1.5rem', background: 'white', boxShadow: '0 30px 50px 0 rgb(1 1 1 / 15%)' }}>
<Headingblock main="Connexion" />
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-row">
<div className="form-group col" style={formgroupStyle}>
<label style={labelStyle}>Adresse email</label>
<input {...register("email")} type="text" className='form-control' style={formcontrolStyle} />
<div className="invalid-feedback" style={invalidStyle}>{errors.email?.message}</div>
</div>
<div className="form-group col" style={formgroupStyle}>
<label style={labelStyle}>Mot de passe</label>
<input {...register("password")} type="password" className='form-control' style={formcontrolStyle} />
<div className="invalid-feedback" style={invalidStyle}>{errors.password?.message}</div>
</div>
</div>
<div className="form-group" style={formgroupStyle}>
<button type="submit" style={Object.assign(btnStyle, btnprimaryStyle)}>
Connexion
</button>
</div>
{
response.status === 'error' && <div style={Object.assign(alertStyle, alertDangerStyle)}>{response.message}</div>
}
</form>
</div>
</div>
</Section>
</>
)
}
import { createContext, useState, useEffect, useContext } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from '../config/firebase'
const AuthContext = createContext({ user: null, userLoading: true });
export const AuthProvider = ({ children }) => {
const [userLoading, setUserLoading] = useState(true);
const [user, setUser] = useState();
useEffect(() => {
return onAuthStateChanged(auth, (user) => {
console.log('autstatechanged');
if (user) {
console.log("1");
setUser(user);
setUserLoading(false);
// ...
} else {
console.log("2");
setUser(null);
}
});
}, []);
return (
<AuthContext.Provider value={[user, userLoading]}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);
Once user is logged in I would like that page being not available anymore so I made a redirect once user is set and userloading is false but the page is rendering before redirect that causes a blink effect.
I wouldn't like return a loading screen I think It should be possible to not render login page if user is logged in

setLoggedIn is not a function react

Okay I'm trying to use global states to store if an user is logged in or not. To do so, I've created a Context file as follows:
import { createContext } from "react";
export const LoginContext= createContext({})
I also have my App.jsx:
import React, { useState } from 'react';
import Component1 from './Component1.jsx';
import Component2 from './Component2.jsx';
import Component3 from './Component3.jsx';
import { LoginContext } from '../Helper/Context.js';
function App(){
const [loggedIn, setLoggedIn] = useState(false);
return (
<LoginContext.Provider value={{loggedIn, setLoggedIn}}>
<Component1 />
<Component2 />
<Component3 />
</LoginContext.Provider>
)
}
export default App;
And then I have my Login component:
import React, {useState, useContext} from "react";
import Axios from 'axios';
import { Link, useHistory } from 'react-router-dom';
import { LoginContext } from "../Helper/Context";
import NavbarHome from "./NavbarHome";
function Login()
{
Axios.defaults.withCredentials = true;
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [loginStatus, setLoginStatus] = useState(false);
const {loggedIn, setLoggedIn} = useContext(LoginContext);
const [error, setErrorStatus] = useState("");
let history = useHistory();
let user = {
id: null,
nombre: null,
email: null
};
const login = () => {
Axios.post('http://localhost:3001/login', {
email: email,
password: password,
}).then((response)=>{
if(!response.data.auth) {
setLoginStatus(false);
setErrorStatus(response.data.message)
setLoggedIn(false);
}
else{
localStorage.setItem("token", response.data.token)
user = {
id: response.data.result[0].id,
name: response.data.result[0].name,
email: response.data.result[0].email
}
setLoginStatus(true);
setLoggedIn(true);
history.push('/perfil');
}
});
};
const userAuthenticated = () => {
Axios.get("http://localhost:3001/isUserAuth", {
headers: {
"x-access-token": localStorage.getItem("token"),
},
}).then((response) => {
console.log(response);
});
}
return(
<div>
<div>
<NavbarHome />
<div>
<div>
<h1>Login</h1>
<p className="label-login">Email:</p>
<input type="text" placeholder="Email..." onChange={(event) => {setEmail(event.target.value);}}/>
<p className="label-login">Contraseña:</p>
<input type="password" placeholder="Password..." onChange={(event) => {setPassword(event.target.value);}}/> <br />
<button onClick={login}>Login</button>
<p style={{marginTop: '1.3rem', color: 'red'}}>{error}</p>
<p><Link to='/registro'>Register here!</Link></p>
</div>
</div>
</div>
</div>
);
}
export default Login;
The output that I receive is this:
It complains about the line where I do this: setLoggedIn(false); or setLoggedIn(true); I'd like to use that state instead of setLoginStatus (which is the one I'm currently using)
Any ideas on how to fix it?

Local storage token Problems

So this problem I am facing for quite some time. Basically Registering user work to some extent. This is what is happening, upon the user being created and me getting the Auth token displayed in the dev-tools/Application and me being pushed to the home as I should.
When I refresh the page I get this error × Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://reactjs.org/link/crossorigin-error for more information. I can fix this by clearing the localStorage. So if every time a new user is created, and if it wants to refresh the page, I will have to clear local storage every time. Which is totally not convenient.
There is another error, The logout handler is bugging, when I press the logout button it is displaying this error TypeError: Cannot read property 'push' of undefined and it pointing out the error is located in the UserContext. I would really appreciate some help really.
User Context
import React from "react";
import { useHistory } from "react-router-dom"
const UserContext = React.createContext();
function getUserFromLocalStorage() {
return localStorage.getItem("authToken")
? JSON.parse(localStorage.getItem("authToken"))
: { username: null, token: null };
}
function UserProvider({ children }) {
const [user, setUser] = React.useState(getUserFromLocalStorage());
const routerHistory = useHistory()
const logoutHandler = () =>{
localStorage.removeItem("authToken");
setUser(user);
routerHistory.push("/")
}
return (
<UserContext.Provider
value={{ user, setUser, logoutHandler }}
>
{children}
</UserContext.Provider>
);
}
export { UserContext, UserProvider };
Login
import React, { useState, } from "react";
import { useHistory } from "react-router-dom"
import axios from "axios";
import { Link } from "react-router-dom";
import "./Signin.css";
import { UserContext } from "../../context/user";
const Login = () => {
const { user, setUser } = React.useContext(UserContext);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const history = useHistory()
const loginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/login",
{ email, password },
config
);
user.authToken = data.token;
setUser(user)
history.push("/");
} catch (error) {
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="signin">
<Link to='/'>
<img src='/audible/logo.png' />
</Link>
<form onSubmit={loginHandler} className="form__container">
<h3>Sign in with your Amazon account</h3>
{error && <span className="error__message">{error}</span>}
<span className='labels'>Email </span>
<input
className="input__field"
type="email"
required
id="email"
onChange={(e) => setEmail(e.target.value)}
value={email}
tabIndex={1}
/>
<span className='signin__forgot'>Password{" "}
<Link className='links' to="/forgotpassword" >
Forgot Password?
</Link>
</span>
<input
className="input__field"
type="password"
required
id="password"
autoComplete="true"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
<button type="submit" className="signin__btn">
Sign In
</button>
<span className='new__sign'>New to Amazon? </span>
<Link to="/register">
<button className='signin__register'>
Create your amazon account
</button>
</Link>
</form>
</div>
);
};
export default Login;
Register
import { useState, } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { useHistory } from "react-router-dom"
const Register = () => {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmpassword, setConfirmPassword] = useState("");
const [error, setError] = useState("");
const routerHistory = useHistory()
const registerHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
if (password !== confirmpassword) {
setPassword("");
setConfirmPassword("");
setTimeout(() => {
setError("");
}, 5000);
return setError("Passwords do not match");
}
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/register",
{
username,
email,
password,
},
config
);
localStorage.setItem("authToken", data.token);
routerHistory.push('/login')
} catch (error) {
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="signin">
<Link to='/'>
<img src='/audible/logo.png' />
</Link>
<form onSubmit={registerHandler} className="form__container">
<h3>Create account</h3>
{error && <span className="error__message">{error}</span>}
<span className='labels'>Username</span>
<input
type="text"
className="input__field"
required
id="name"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<span className='labels'>Email</span>
<input
type="email"
className="input__field"
required
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<span className='labels'>Password</span>
<input
type="password"
required
id="password"
className="input__field"
autoComplete="true"
placeholder="At least 6 characters"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<span className='labels'>Re-enter password</span>
<input
type="password"
required
id="confirmpassword"
className="input__field"
autoComplete="true"
value={confirmpassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
<button type="submit" className="register__btn">
Create your Amazon account
</button>
<span >
Already have an account? <Link className='links' to="/login">Login</Link>
</span>
</form>
</div>
);
};
export default Register;
Login Link
import React from "react";
import { Link, useHistory } from "react-router-dom";
import { CartContext } from "../../context/cart";
import { UserContext } from "../../context/user";
export default function LoginLink() {
const { user, logoutHandler } = React.useContext(UserContext);
const { clearCart } = React.useContext(CartContext);
if (user.authToken) {
return (
<button
onClick={() => {
logoutHandler();
clearCart()
}}
className="login-btn"
>
logout
</button>
);
}
return <Link to="/login">Signin</Link>;
}

Logout funcionality via local storage

So here I have Login funcionality via local storage token. I am getting the token upon user being created in The dev tools/Application it is redirecting me to the home that is working. The thing that is not working is this. Creating an user it is working but when it loads it should show logout instead of login, and should hide the cart Component. Where am I making a mistake
Context Api
import React from "react";
const UserContext = React.createContext();
function getUserFromLocalStorage() {
return localStorage.getItem("authToken")
? JSON.parse(localStorage.getItem("authToken"))
: { username: null, token: null };
}
function UserProvider({ children }) {
const [user, setUser] = React.useState(getUserFromLocalStorage());
const history = useHistory();
const logoutHandler = () =>{
localStorage.removeItem("user");
history.push("/")
}
return (
<UserContext.Provider
value={{ user, logoutHandler }}
>
{children}
</UserContext.Provider>
);
}
export { UserContext, UserProvider };
Login Link
import React from "react";
import { Link } from "react-router-dom";
import { UserContext } from "../../context/user";
import { useHistory } from "react-router-dom"
export default function LoginLink() {
const { user, logoutHandler } = React.useContext(UserContext);
if (user.authToken) {
return (
<button
onClick={() => {
logoutHandler();
}}
className="login-btn"
>
logout
</button>
);
}
return <Link to="/login">login</Link>;
}
Header
import React from 'react';
import { Link, useHistory } from "react-router-dom";
import Search from './Search';
import './Header.css'
import SearchBooks from './SearchBooks';
import LoginLink from '../Signin/LoginLink';
import CartLink from '../Cart/CartLink';
import { UserContext } from '../../context/user';
const Header = () => {
const { user } = React.useContext(UserContext);
return (
<div className='header__container'>
<Link to='/'>
<img src='/audi.png' />
</Link>
<li>
<LoginLink />
</li>
{user.authToken &&(
<CartLink />
)
}
</div>
)
}
export default Header
Login Component
import { useState, } from "react";
import { useHistory } from "react-router-dom"
import axios from "axios";
import { Link } from "react-router-dom";
import "./Signin.css";
const Login = () => {
const { user, setUser } = React.useContext(UserContext);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const history = useHistory()
const loginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post(
"http://localhost:5000/api/auth/login",
{ email, password },
config
);
localStorage.setItem("authToken", data.token);
setUser(user)
history.push("/");
} catch (error) {
if (error.response) {
setError(error.response.data.error);
}
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="login-screen">
<form onSubmit={loginHandler} className="login-screen__form">
<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="Email address"
onChange={(e) => setEmail(e.target.value)}
value={email}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{" "}
<Link to="/forgotpassword" className="login-screen__forgotpassword">
Forgot Password?
</Link>
</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary">
Login
</button>
<span className="login-screen__subtext">
Don't have an account? <Link to="/register">Register</Link>
</span>
</form>
</div>
);
};
export default Login;
After you login, you have only set the authToken into your localStorage and not in your Provider. You'll need to call setUser after you login in order for Header component to know user is logged in.

Categories