I am creating quote app using react,graphql,apollo-client,mongodb atlas. I am storing authentication token in the localStorage when user login and remove it when user logout.I have a profile page in which it shows the detail of loggedin user.
The issue is that when i logout and then login another user,it shows the detail of previous user and when i refresh the page then it shows the current user details.so, how can i get the new user's detail without refreshing the page?
CreateQuote component :
import { useMutation } from "@apollo/client";
import React, { useState } from "react";
import { CREATE_QUOTE } from "../gqloperations/mutations";
function CreateQuote() {
const [quote, setQuote] = useState("");
const [createQuote, { loading, error, data }] = useMutation(CREATE_QUOTE, {
refetchQueries: ["getAllQuotes", "getMyProfile"],
});
data && console.log(data);
const handleSubmit = () => {
createQuote({
variables: {
name: quote,
},
});
};
if (loading) {
return <h1>loading...</h1>;
}
return (
<div className="container">
{error && <div className="red card-panel">{error.message}</div>}
{data && <div className="green card-panel">{data.quote}</div>}
<form onSubmit={handleSubmit}>
<input
type="text"
value={quote}
onChange={(e) => setQuote(e.target.value)}
placeholder="write your quote"
/>
<button className="btn green" type="submit" onClick={handleSubmit}>
create
</button>
</form>
</div>
);
}
export default CreateQuote;
Login Component :
import React, { useState } from "react";
import { useNavigate } from "react-router";
import { Link } from "react-router-dom";
import { LOGIN_USER } from "../gqloperations/mutations";
export default function Login() {
const [formData, setFormData] = useState({ email: "", password: "" });
const [signinUser, { loading, data, error }] = useMutation(LOGIN_USER, {
refetchQueries: ["getMyProfile"],
onCompleted(data) {
localStorage.setItem("token", data.user.token);
navigate("/");
},
});
const navigate = useNavigate();
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
signinUser({
variables: {
userSignin: formData,
},
});
setFormData({ email: "", password: "" });
};
if (loading) return <h1>Loading</h1>;
// if (data) {
// localStorage.setItem("token", data.user.token);
// navigate("/");
// }
return (
<>
{error && <div className="red card-panel">{error.message}</div>}
{data && data.signupUser && (
<div className="green card-panel">
{data.user.token} login successfully
</div>
)}
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="email"
/>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
placeholder="password"
/>
<Link to="/login">
<p>Don't have an account ?</p>
</Link>
<button type="submit" className="green btn">
Login
</button>
</form>
</div>
</>
);
}
Profile component:
import React, { useEffect } from "react";
import { useQuery } from "@apollo/client";
import { GET_MY_PROFILE } from "../gqloperations/queries";
import { useNavigate } from "react-router";
export default function Profile() {
const { loading, error, data, refetch } = useQuery(GET_MY_PROFILE);
useEffect(() => {
refetch();
}, [data]);
const navigate = useNavigate;
if (!localStorage.getItem("token")) {
navigate("/login");
}
if (loading) return <h1>Loading...</h1>;
if (error) console.log(error);
return (
<div className="container">
<div className="center-align">
<img
style={{ border: "2px solid black", marginTop: "10px" }}
className="circle"
src={`https://robohash.org/${data.user.firstName}.png?size=200x200`}
alt=""
/>
<h5>
{data.user.firstName} {data.user.lastname}
</h5>
<h5>Email-{data.user.email}</h5>
</div>
<h3>Your quotes</h3>
{data.user.quotes.map((quote) => {
return (
<blockquote>
<h6>{quote.name}</h6>
</blockquote>
);
})}
</div>
);
}
Navbar component: (contains Logout button)
import React from "react";
import { useNavigate } from "react-router";
import { Link } from "react-router-dom";
function NavBar() {
const token = localStorage.getItem("token");
const navigate = useNavigate();
return (
<div>
<nav>
<div className="nav-wrapper">
<Link to="/" className="brand-logo left">
Quotes
</Link>
<ul id="nav-mobile" className="right">
{token ? (
<>
<li>
<Link to="/profile">Profile</Link>
</li>
<li>
<Link to="/create">Create</Link>
</li>
<li>
<button
className="red btn"
onClick={() => {
localStorage.removeItem("token");
navigate("/login");
}}
>
Logout
</button>
</li>
</>
) : (
<>
<li>
<Link to="/login">Login</Link>
</li>
<li>
<Link to="/signup">Signup</Link>
</li>
</>
)}
</ul>
</div>
</nav>
</div>
);
}
export default NavBar;
Edit : after slothOverlord's answer ,the updates are as below: Navbar component
import React from "react";
import { useNavigate } from "react-router";
import { Link } from "react-router-dom";
import { client } from "../index.js";
function NavBar() {
const token = localStorage.getItem("token");
const navigate = useNavigate();
return (
<div>
<nav>
<div className="nav-wrapper">
<Link to="/" className="brand-logo left">
Quotes
</Link>
<ul id="nav-mobile" className="right">
{token ? (
<>
<li>
<Link to="/profile">Profile</Link>
</li>
<li>
<Link to="/create">Create</Link>
</li>
<li>
<button
className="red btn"
onClick={async() => {
localStorage.removeItem("token");
await client.resetStore();
navigate("/login");
}}
>
Logout
</button>
</li>
</>
) : (
<>
<li>
<Link to="/login">Login</Link>
</li>
<li>
<Link to="/signup">Signup</Link>
</li>
</>
)}
</ul>
</div>
</nav>
</div>
);
}
export default NavBar;
Login component :
import { useMutation } from "@apollo/client";
import React, { useState } from "react";
import { useNavigate } from "react-router";
import { Link } from "react-router-dom";
import { LOGIN_USER } from "../gqloperations/mutations";
export default function Login() {
const [formData, setFormData] = useState({ email: "", password: "" });
const [signinUser, { loading, data, error ,client}] = useMutation(LOGIN_USER, {
refetchQueries: ["getMyProfile"],
onCompleted(data) {
localStorage.setItem("token", data.user.token);
client.clearStore();
navigate("/");
},
});
const navigate = useNavigate();
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault();
signinUser({
variables: {
userSignin: formData,
},
});
setFormData({ email: "", password: "" });
};
if (loading) return <h1>Loading</h1>;
// if (data) {
// localStorage.setItem("token", data.user.token);
// navigate("/");
// }
return (
<>
{error && <div className="red card-panel">{error.message}</div>}
{data && data.signupUser && (
<div className="green card-panel">
{data.user.token} login successfully
</div>
)}
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="email"
/>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
placeholder="password"
/>
<Link to="/login">
<p>Don't have an account ?</p>
</Link>
<button type="submit" className="green btn">
Login
</button>
</form>
</div>
</>
);
}
other components are same as above.