T
TanStack13mo ago
vicious-gold

Can you redirect in server functions?

Is it possible to redirect in a server function? It's not working for me. I see a uncaught (in promise) error client-side. Error:
Uncaught (in promise)
isRedirect: true
params: {teamId: 3}
statusCode: 307
to: "/$teamId"
[[Prototype]]: Object
Uncaught (in promise)
isRedirect: true
params: {teamId: 3}
statusCode: 307
to: "/$teamId"
[[Prototype]]: Object
Code:
const signIn = createServerFn('POST', async (data: z.infer<typeof loginFormSchema>, ctx) => {
const session = await createClient(ctx).auth.signInWithPassword({
email: data.email,
password: data.password,
});

const userId = session.data.user?.id;
if (!userId) {
throw session.error || new Error('An error occurred');
}

const firstTeam = await db.query.teamMemberTable.findFirst({
where: (teamMember, { eq }) => eq(teamMember.userId, userId),
orderBy: (teamMember, { asc }) => asc(teamMember.createdAt),
with: { team: true },
});

if (!firstTeam) {
throw redirect({ to: '/login', search: { error: 'no-team-found' } });
}

throw redirect({
to: '/$teamId',
params: { teamId: firstTeam.team.id },
headers: ctx.request.headers,
});
});

async function login(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();

const data = new FormData(e.currentTarget);
const payload = loginFormSchema.parse(Object.fromEntries(data.entries()));

await signIn(payload);
}

export default function Page() {
// ...
return (
// ...
<form onSubmit={login}>
)
}
const signIn = createServerFn('POST', async (data: z.infer<typeof loginFormSchema>, ctx) => {
const session = await createClient(ctx).auth.signInWithPassword({
email: data.email,
password: data.password,
});

const userId = session.data.user?.id;
if (!userId) {
throw session.error || new Error('An error occurred');
}

const firstTeam = await db.query.teamMemberTable.findFirst({
where: (teamMember, { eq }) => eq(teamMember.userId, userId),
orderBy: (teamMember, { asc }) => asc(teamMember.createdAt),
with: { team: true },
});

if (!firstTeam) {
throw redirect({ to: '/login', search: { error: 'no-team-found' } });
}

throw redirect({
to: '/$teamId',
params: { teamId: firstTeam.team.id },
headers: ctx.request.headers,
});
});

async function login(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();

const data = new FormData(e.currentTarget);
const payload = loginFormSchema.parse(Object.fromEntries(data.entries()));

await signIn(payload);
}

export default function Page() {
// ...
return (
// ...
<form onSubmit={login}>
)
}
5 Replies
extended-salmon
extended-salmon13mo ago
You need to wrap it in the useServerFn hook I believe
vicious-gold
vicious-goldOP13mo ago
Hmm yeah the redirect works now but sadly the cookies from ctx.request.headers aren't being set
extended-salmon
extended-salmon13mo ago
Yeah that I'm unsure on
extended-salmon
extended-salmon13mo ago
Server Functions | TanStack Router React Docs
What are Server Functions? Server functions allow you to specify specific function to run only on the server. They are used to perform tasks that should never be directly exposed to the client.
vicious-gold
vicious-goldOP13mo ago
Thanks, didn't know about these functions. Using setHeader works!
setHeader('Set-Cookie', ctx.request.headers.getSetCookie());

throw redirect({
to: '/$teamId',
params: {
teamId: firstTeamId,
},
});
setHeader('Set-Cookie', ctx.request.headers.getSetCookie());

throw redirect({
to: '/$teamId',
params: {
teamId: firstTeamId,
},
});

Did you find this page helpful?