BA
Better Auth•4mo ago
Imam

refetch() from useSession() return cached data

Why does calling refetch() from useSession() return cached data? This only happens in production. The updated data is returned after approximately 50 seconds. In development, it always returns fresh data immediately after calling refetch()
12 Replies
Imam
ImamOP•4mo ago
client code:
const { data: session, refetch } = authClient.useSession();

...

const onSubmit: SubmitHandler<UpdateUserSchema> = (values) => {
updateAccountMutation.mutate(
{
params: { id: session.user.id },
body: updateData,
},
{
onSuccess: async () => {
toast.success('Account updated successfully');

// Refetch session data first to get updated image info
refetch();
},
onError: (error) => {
toast.error(error.message || 'Failed to update profile');
},
}
);
}
const { data: session, refetch } = authClient.useSession();

...

const onSubmit: SubmitHandler<UpdateUserSchema> = (values) => {
updateAccountMutation.mutate(
{
params: { id: session.user.id },
body: updateData,
},
{
onSuccess: async () => {
toast.success('Account updated successfully');

// Refetch session data first to get updated image info
refetch();
},
onError: (error) => {
toast.error(error.message || 'Failed to update profile');
},
}
);
}
server code:
await auth.api.updateUser({
body: {
...rest,
username:
user.username === rest.username ? undefined : rest.username,
image: newFileName,
},
headers: context.c.req.raw.headers,
});
await auth.api.updateUser({
body: {
...rest,
username:
user.username === rest.username ? undefined : rest.username,
image: newFileName,
},
headers: context.c.req.raw.headers,
});
Sorry, can somebody help me?, it s been days, i need a clue for this issue @bekacru @Ping thank you
bekacru
bekacru•4mo ago
are you using cookie cache?
Imam
ImamOP•4mo ago
i think no
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { admin, username } from 'better-auth/plugins';

import { db } from '@repo/db';
import {
accountTable,
sessionTable,
userTable,
verificationTable,
} from '@repo/db/model';

export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: 'pg',
schema: {
user: userTable,
session: sessionTable,
account: accountTable,
verification: verificationTable,
},
}),
user: {
additionalFields: {
companyId: {
type: 'string',
nullable: true,
},
photo: {
type: 'string',
nullable: true,
},
deletedAt: {
type: 'date',
nullable: true,
},
},
},
emailAndPassword: {
enabled: true,
},
plugins: [
username(),
admin({
adminUserIds: ['matt'],
}),
],
session: {
expiresIn: 60 * 60 * 24 * 1,
},
advanced: {
defaultCookieAttributes: {
domain: process.env.DOMAIN,
},
},
trustedOrigins: [process.env.NEXT_PUBLIC_WEB_BASE_URL!],
});
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { admin, username } from 'better-auth/plugins';

import { db } from '@repo/db';
import {
accountTable,
sessionTable,
userTable,
verificationTable,
} from '@repo/db/model';

export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: 'pg',
schema: {
user: userTable,
session: sessionTable,
account: accountTable,
verification: verificationTable,
},
}),
user: {
additionalFields: {
companyId: {
type: 'string',
nullable: true,
},
photo: {
type: 'string',
nullable: true,
},
deletedAt: {
type: 'date',
nullable: true,
},
},
},
emailAndPassword: {
enabled: true,
},
plugins: [
username(),
admin({
adminUserIds: ['matt'],
}),
],
session: {
expiresIn: 60 * 60 * 24 * 1,
},
advanced: {
defaultCookieAttributes: {
domain: process.env.DOMAIN,
},
},
trustedOrigins: [process.env.NEXT_PUBLIC_WEB_BASE_URL!],
});
here is my repo: https://github.com/mamlzy/datalearning-repro/tree/main
bekacru
bekacru•4mo ago
you should use authClient.updateUser instead of calling the server method. This wil handle refetching the session itself
Imam
ImamOP•4mo ago
i mean i have a lot of server logic on the server such as, saving profile picture on the api folder, change password, etc. i couldn't do that stuff on client. what do you think? oh my repo is not updated yet, i have account page for updating user profile and info here i did something like this on the server (i'm not using better-auth api to update the user)
const updatedUser = await db.transaction(async (tx) => {
let result: User;

if (imageFile) {
// Handle image upload
// Validate file size (2MB = 2 * 1024 * 1024 bytes)
const maxSize = 2 * 1024 * 1024; // 2MB
if (imageFile.size > maxSize) {
throw new ORPCError('BAD_REQUEST', {
message: 'File size exceeds 2MB limit',
});
}

// Validate file type (only images)
const allowedTypes = [
'image/jpeg',
'image/jpg',
'image/png',
'image/gif',
'image/webp',
];
if (!allowedTypes.includes(imageFile.type)) {
throw new ORPCError('BAD_REQUEST', {
message:
'Only image files (JPEG, JPG, PNG, GIF, WebP) are allowed',
});
}

const fileBuffer = Buffer.from(await imageFile.arrayBuffer());

extension and file extension
const fileExt = path.extname(imageFile.name);
const fileNameWithoutExt = path.basename(imageFile.name, fileExt);
const newFileName = `${fileNameWithoutExt}-${createId()}${fileExt}`;

const uploadDir = path.join(CWD, 'public', 'pp');
const filePath = path.join(uploadDir, newFileName);

try {
const updatedUser = await service.updateUserById({
tx,
id: user.id,
payload: {
...rest,
image: newFileName,
},
});

// Ensure upload directory exists
await fs.mkdir(uploadDir, { recursive: true });

// Write the file
await fs.writeFile(filePath, fileBuffer);

result = updatedUser;
const updatedUser = await db.transaction(async (tx) => {
let result: User;

if (imageFile) {
// Handle image upload
// Validate file size (2MB = 2 * 1024 * 1024 bytes)
const maxSize = 2 * 1024 * 1024; // 2MB
if (imageFile.size > maxSize) {
throw new ORPCError('BAD_REQUEST', {
message: 'File size exceeds 2MB limit',
});
}

// Validate file type (only images)
const allowedTypes = [
'image/jpeg',
'image/jpg',
'image/png',
'image/gif',
'image/webp',
];
if (!allowedTypes.includes(imageFile.type)) {
throw new ORPCError('BAD_REQUEST', {
message:
'Only image files (JPEG, JPG, PNG, GIF, WebP) are allowed',
});
}

const fileBuffer = Buffer.from(await imageFile.arrayBuffer());

extension and file extension
const fileExt = path.extname(imageFile.name);
const fileNameWithoutExt = path.basename(imageFile.name, fileExt);
const newFileName = `${fileNameWithoutExt}-${createId()}${fileExt}`;

const uploadDir = path.join(CWD, 'public', 'pp');
const filePath = path.join(uploadDir, newFileName);

try {
const updatedUser = await service.updateUserById({
tx,
id: user.id,
payload: {
...rest,
image: newFileName,
},
});

// Ensure upload directory exists
await fs.mkdir(uploadDir, { recursive: true });

// Write the file
await fs.writeFile(filePath, fileBuffer);

result = updatedUser;
why this caching issue only happens in production? the refetch from useSession updates the user info, but only in dev
bekacru
bekacru•4mo ago
refetch from useSession should work. But the other option you can try is use authClient.getSession with react query
Imam
ImamOP•4mo ago
i did try that too, wrapping getSession with react-query also has the same caching issue (only in production)
bekacru
bekacru•4mo ago
them the caching is happening on the server side make sure api routes are fully dynamic and awlays return fresh data
Imam
ImamOP•4mo ago
i will try to fix thiss issue again, like in 3 hours from now. i'll give you an update later @bekacru i have trying to console.log every route in my server, it always showing updated data, but the useSession in client always returns cache data for like ~50 seconds.
app.use('*', async (c, next) => {
const session = await auth.api.getSession({ headers: c.req.raw.headers });

console.log('session.user => ', session?.user);

if (!session) {
c.set('user', null);
c.set('session', null);
return next();
}

c.set('user', session.user);
c.set('session', session.session);
return next();
});
app.use('*', async (c, next) => {
const session = await auth.api.getSession({ headers: c.req.raw.headers });

console.log('session.user => ', session?.user);

if (!session) {
c.set('user', null);
c.set('session', null);
return next();
}

c.set('user', session.user);
c.set('session', session.session);
return next();
});
Imam
ImamOP•4mo ago
GitHub
GitHub - mamlzy/orpc-experiment
Contribute to mamlzy/orpc-experiment development by creating an account on GitHub.
Imam
ImamOP•4mo ago
Oh even with authClient.updateUser still caching in production, what happened here, is it only in my side or in better-auth, im pretty confused here
const updateAccountMutation = useMutation({
mutationFn: async (values: UpdateUserSchema) => {
if (!session) throw new Error('Unauthorized');
console.log('runs');

const { error } = await authClient.updateUser({
name: values.name,
});

if (error) throw new Error(error.message);
},
});
const updateAccountMutation = useMutation({
mutationFn: async (values: UpdateUserSchema) => {
if (!session) throw new Error('Unauthorized');
console.log('runs');

const { error } = await authClient.updateUser({
name: values.name,
});

if (error) throw new Error(error.message);
},
});
Imam
ImamOP•4mo ago
I have fixed the issue, its all about my caching things on my vps 😔 sorry for bothering you @bekacru, thank you for helping me!
No description

Did you find this page helpful?