What I want to achieve here is, whenever a user logs in, I want to store the data returned because the data holds an ID that I would use to fetch data in other routes.
When a user successfully logs in, he would be redirected to the /home route and the ID gotten from the session would be used to fetch data. Everything works fine initially, but if I refresh the home page, the user becomes null.
This is what my […nextauth].js looks like.
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import axios from "axios";
export default NextAuth({
providers: [
CredentialsProvider({
name: "credentials",
credentials: {
username: { label: "Username", type: "text", placeholder: "justin" },
password: {label: "Password",type: "password",placeholder: "******"},
},
async authorize(credentials, req) {
const url = req.body.callbackUrl.split("/auth")[0];
const { username, password } = credentials;
const user = await axios({
url: `${url}/api/user/login`,
method: "POST",
data: {
username: username,
password: password,
},
"content-type": "application/json",
})
.then((res) => {
return res.data;
})
.catch((err) => {
if (err.response.data) {
throw new Error(err.response.data);
} else {
return null;
}
return null;
});
return user;
},
}),
],
callbacks: {
jwt: ({ token, user }) => {
if (user) {
token.user = user;
}
return token;
},
session: ({ session, token }) => {
if (token) {
session.user = token.user;
}
return session;
},
},
pages: {
signIn: "/auth/login",
newUser: "/auth/register",
},
});
and this is what my /home route looks like
import Card from "@/components/card/Card";
import React, { useEffect, useState } from "react";
import styles from "./home.module.css";
import { Ubuntu } from "@next/font/google";
import { useSession } from "next-auth/react";
import { useDispatch, useSelector } from "react-redux";
const ubuntu = Ubuntu({ weight: "500", subsets: ["cyrillic"] });
const getData = async (id) => {
const res = await fetch({
url: "http://localhost:3000/api/note/getall",
method: "POST",
"content-type": "application/json",
data: {
id: id,
},
});
if (!res.ok) {
console.log(id);
throw new Error("Unable to fetch");
} else {
return res.json();
console.log(res);
}
};
function home() {
const colors = ["#E9F5FC", "#FFF5E1", "#FFE9F3", "#F3F5F7"];
const random = Math.floor(Math.random() * 5);
const rc = colors[random];
const [pop, setPop] = useState("none");
const { user } = useSelector((state) => state.user);
const getDataa = async () => {
console.log(user)
const data = await getData(user._id);
console.log(data);
};
useEffect(() => {
if (user) {
alert(user)
}
}, []);
return (
<div className={styles.home}>
<header>
<h3 className={ubuntu.className}>
Hello, <br /> {user?.username}!
</h3>
<input type="text" placeholder="search" />
</header>
<div className={styles.nav}>
<h1 className={ubuntu.className}>Notes</h1>
</div>
<div className={styles.section}>
<div className={styles.inner}>
{/* {data &&
data.map((e) => (
<Card
rawData={e}
color={colors[Math.floor(Math.random() * colors.length)]}
/>
))} */}
</div>
</div>
<div className="new"></div>
</div>
);
}
export default home;
2
Answers
Add this
component
to your App.js file :Now in your App function instead of returning
<Component {...pageProps} />
you check first if thecomponent
hasauth
property, so you wrapp it with<Auth>
to ensure that every component that requires session will only mount when the session finishes loading (that’s why the user isnull
because the session is still loading)finally you add
.auth = {}
to every page in whitch you want the session to be defined (Home in your case)This also helps to redirect user to
/sign-in
page if the session is expiredThis code seems like it would create a problem / race-condition since you’re mixing two different async promise handling styles:
It should either be this:
Or this: