useSession weird behaviour

Hi, I have some problems with useSession, it keeps giving me date null even though I am logged in. I'm testing it with dev and turbopack. This happens when I do a page refresh, so if I logout and log in the hook works, but if I do a page refresh it no longer works returning null. auth-client.ts
import { createAuthClient } from "better-auth/react";
import { inferAdditionalFields } from "better-auth/client/plugins";
import type { auth } from "@/auth";

export const authClient = createAuthClient({
plugins: [inferAdditionalFields<typeof auth>()],
baseURL: process.env.BETTER_AUTH_URL! // Optional if the API base URL matches the frontend
});

export const { signIn, signOut, useSession, getSession } = authClient;
import { createAuthClient } from "better-auth/react";
import { inferAdditionalFields } from "better-auth/client/plugins";
import type { auth } from "@/auth";

export const authClient = createAuthClient({
plugins: [inferAdditionalFields<typeof auth>()],
baseURL: process.env.BETTER_AUTH_URL! // Optional if the API base URL matches the frontend
});

export const { signIn, signOut, useSession, getSession } = authClient;
auth.ts
import { betterAuth } from 'better-auth'
import { prismaAdapter } from 'better-auth/adapters/prisma'
import { prisma } from './lib/db'
import { sendVerificationMail } from './lib/mail'

export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: 'postgresql'
}),
user: {
additionalFields: {
dob: {
type: 'string',
required: true
}
}
},
emailAndPassword: {
enabled: true,
minPasswordLength: 4,
maxPasswordLength: 32,
requireEmailVerification: true
},
emailVerification: {
sendVerificationEmail: async ({ user, url }) => await sendVerificationMail(user.email, url),
sendOnSignUp: true,
autoSignInAfterVerification: true,
},
advanced: {
cookiePrefix: 'diveme'
},
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
}
}
})
import { betterAuth } from 'better-auth'
import { prismaAdapter } from 'better-auth/adapters/prisma'
import { prisma } from './lib/db'
import { sendVerificationMail } from './lib/mail'

export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: 'postgresql'
}),
user: {
additionalFields: {
dob: {
type: 'string',
required: true
}
}
},
emailAndPassword: {
enabled: true,
minPasswordLength: 4,
maxPasswordLength: 32,
requireEmailVerification: true
},
emailVerification: {
sendVerificationEmail: async ({ user, url }) => await sendVerificationMail(user.email, url),
sendOnSignUp: true,
autoSignInAfterVerification: true,
},
advanced: {
cookiePrefix: 'diveme'
},
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
}
}
})
No description
10 Replies
snouzy
snouzy•2d ago
Hey, you are trying to access the useSession in a server context, which is a hook reserved to client side. What you should do, in a server context, is something like this :
// src/lib/auth.ts
export const auth = betterAuth({...});
// src/lib/auth.ts
export const auth = betterAuth({...});
// app/dashboard/layout.tsx
const headerStore = await headers();
const user = await auth.api.getSession({ headers: headerStore });
// app/dashboard/layout.tsx
const headerStore = await headers();
const user = await auth.api.getSession({ headers: headerStore });
If you really want to use useSession(), you should add "use client" in the top of your file
FrancyMak
FrancyMakOP•2d ago
Nope, it's a client component That's why i specified client component
FrancyMak
FrancyMakOP•2d ago
No description
FrancyMak
FrancyMakOP•2d ago
Here you go đŸ™‚
snouzy
snouzy•2d ago
Oh okay, so in the first place you cannot do session.data!.user.id because in the first render, session.data will not be defined, since it's client side it will have a little throttle (bcs of the cookie storage). So the error say that he's waiting for the user is right. Here's what i did :
export const useCurrentUser = () => {
const session = useSession();
const user = session.data?.user;

if (!user) {
return null;
}

return user;
};
export const useCurrentUser = () => {
const session = useSession();
const user = session.data?.user;

if (!user) {
return null;
}

return user;
};
export const useCurrentSession = () => {
const session = useSession();
const sessionData = session.data;

if (!sessionData) {
return null;
}

return sessionData;
};
export const useCurrentSession = () => {
const session = useSession();
const sessionData = session.data;

if (!sessionData) {
return null;
}

return sessionData;
};
FrancyMak
FrancyMakOP•2d ago
Ok but the user will be null anyway export function Notifications() { const user = useCurrentUser() const { data: notifications, refetch } = useNotificationsQuery(user.id) I already have that hook but the user returns null so i can't conditionally call hooks
snouzy
snouzy•2d ago
Does it work if you call useCurrentUser right in useNotificationsQuery ?
FrancyMak
FrancyMakOP•2d ago
No because user is null The argument of type ‘string | undefined’ is not assignable to the parameter of type ‘string’. The type ‘undefined’ is not assignable to the type ‘string’.
snouzy
snouzy•2d ago
Is it possible for you to provide a minimal reproduction example via github ? I'll be happy to help
daveycodez
daveycodez•2d ago
If you're using TanStack Query I suggest my package for useSession https://github.com/daveyplate/better-auth-tanstack

Did you find this page helpful?