Cookies update on page reload
Answered
Siberian posted this in #help-forum
SiberianOP
Hi there. I want to update cookie expiration time on page reload. However calling it in my page.tsx or extracted "use server" function is yelling about server stuff on render
Answered by Ray
// middleware.ts
export async function middleware(request: NextRequest) {
const uuid = request.cookies.get("uuid");
if (uuid?.value) {
const newExpiration = new Date();
newExpiration.setMinutes(newExpiration.getMinutes() + 15);
const ticketId = "";
sql`
UPDATE basket
SET date = ${newExpiration.toISOString()}
WHERE (uuid =${uuid.value}) AND (ticket_code =${ticketId})
`;
const res = new NextResponse();
res.cookies.set({
name: "uuid",
value: uuid.value,
expires: newExpiration,
});
return res;
}
}54 Replies
SiberianOP
?
Largehead hairtail
Hi @Ratonero Bodeguero Andaluz ,
Check this doc
Check this doc
You can set the expires for cookies.
Original message was deleted
SiberianOP
I have a cookie named 'uuid' which contains uuidv4 as a value and its expiration is set to 15min
Every time user reloads page I want that expiration time to 'reset' back to 15min if that cookie still exists
Its working when I put a function with "use server" on a client side inside useEffect, but preferably I would do this on server side
Every time user reloads page I want that expiration time to 'reset' back to 15min if that cookie still exists
Its working when I put a function with "use server" on a client side inside useEffect, but preferably I would do this on server side
Largehead hairtail
and also
cookies is server action, so you should use it in server component or api route@Largehead hairtail and also `cookies` is server action, so you should use it in server component or api route
SiberianOP
Yeah, I know how to set up a cookie, but updating it with either server-action funcion or api route doesnt work, first one is yelling about waterfall on render, second is just not doing anything to a cookie
Largehead hairtail
Share me your code here.
SiberianOP
// api/route.ts
import { cookies } from "next/headers";
export async function POST(req: Request){
const {uuid,newExpiration} = await req.json();
const date = new Date(newExpiration)
cookies().set('uuid',uuid.value,{expires:date})
return Response.json(true)
}// page.tsx
const newExpiration = new Date();
newExpiration.setMinutes(newExpiration.getMinutes() + 15);
if(uuid){
//TODO: UPDATE COOKIES
const res = await fetch(`http://192.168.8.112:3000/${params.slug}/api`,{
method:'POST',
body:JSON.stringify({uuid,newExpiration})
})
console.log(res)
sql`
UPDATE basket
SET date = ${newExpiration.toISOString()}
WHERE (uuid =${uuid.value}) AND (ticket_code =${params.slug})
`
}
Largehead hairtail
export const POST = async (req: Request) => {
const body = await req.json();
const response = NextResponse.json({
success: true,
});
response.cookies.set(body.name, body.value);
return response;
};reference this example if you prefer to use api route.
I hope above practice helps you.
SiberianOP
I would rather not be calling api on server side
Largehead hairtail
Ah, I suggest to delete old and create new.
@Largehead hairtail Ah, I suggest to delete old and create new.
SiberianOP
well its not working in any way, changed name and value and it didnt add new cookie
but its in response
Best if I could just call a function that would deal with it
Largehead hairtail
If you prefer function to api, you should use server action.
@Largehead hairtail If you prefer function to api, you should use server action.
SiberianOP
its funny actually. it gives me this error
[Error]: Cookies can only be modified in a Server Action or Route Handler.Largehead hairtail
// common.ts
'use server';
import { cookies } from 'next/headers';
export const setCookie = async (name: string, value: string) => {
cookies().set(name, value)
}SiberianOP
and this is my server-action.ts file
"use server";
import { sql } from "@vercel/postgres";
import { RequestCookie } from "next/dist/compiled/@edge-runtime/cookies";
import { cookies } from "next/headers";
export const updateCookie = async (uuid:RequestCookie,ticketId:string) =>{
const newExpiration = new Date();
newExpiration.setMinutes(newExpiration.getMinutes() + 15);
if(uuid){
//TODO: UPDATE COOKIES
cookies().delete('uuid')
cookies().set('uuid',uuid.value,{expires:newExpiration})
sql`
UPDATE basket
SET date = ${newExpiration.toISOString()}
WHERE (uuid =${uuid.value}) AND (ticket_code =${ticketId})
`
}
}is it even possible to update cookie from server, or should it be done only on client side (calling server by serverAction or apiRoute)?
Largehead hairtail
cookies is server action, so if you want to call the func in client, you should make server action common file like above my practice.
SiberianOP
yes, but my
page.tsx is not using client with "use client"@Largehead hairtail ts
// common.ts
'use server';
import { cookies } from 'next/headers';
export const setCookie = async (name: string, value: string) => {
cookies().set(name, value)
}
Largehead hairtail
You can call
setCookie in both of client and server components. Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options
at setCookie (./src/server-actions/sql/common.ts:15:61)use cookies-next library
Largehead hairtail
Yeah, look at the error message.
That says the func is called in client component.
@averydelusionalperson use cookies-next library
SiberianOP
going to read about it
@Largehead hairtail That says the func is called in client component.
SiberianOP
where it says that?
Largehead hairtail
Error: Cookies can only be modified in a Server Action or Route Handler
SiberianOP
so basically cookies can be modified only on client-side?
Largehead hairtail
no, what i mean: you're calling the cookies function in client component.
@Largehead hairtail no, what i mean: you're calling the cookies function in client component.
SiberianOP
yeah.. no. Im calling it on my server page.tsx
which is not using "use client"
@Siberian Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options
at setCookie (./src/server-actions/sql/common.ts:15:61)
https://nextjs-faq.com/server-action-call-inside-server-component-rendering
and read this for this error
and read this for this error
Largehead hairtail
check the parent component, just like layout
server action need to be use with form, useEffect or event handler
not the page render
Largehead hairtail
if 'use client' is used in parent component like layout.tsx, your current page.tsx is client
@Largehead hairtail check the parent component, just like layout
SiberianOP
it doesnt allow me to use useEffect or useState, so I would say its not client
@Ray https://nextjs-faq.com/server-action-call-inside-server-component-rendering
and read this for this error
SiberianOP
thanks, that clarifies it
the best would be do it in middleware for you case
@Ray the best would be do it in middleware for you case
SiberianOP
okay, gonna try it, if not im gonna try that npm package
btw. for client-side what would be best to use instead of useEffect for function that needs to be triggered only once?
btw. for client-side what would be best to use instead of useEffect for function that needs to be triggered only once?
Largehead hairtail
you can use useLayoutEffect
@Siberian okay, gonna try it, if not im gonna try that npm package
btw. for client-side what would be best to use instead of useEffect for function that needs to be triggered only once?
I would set the cookie on server side instead but if you really want to set it on client, then set it inside useEffect
@Siberian okay, gonna try it, if not im gonna try that npm package
btw. for client-side what would be best to use instead of useEffect for function that needs to be triggered only once?
// middleware.ts
export async function middleware(request: NextRequest) {
const uuid = request.cookies.get("uuid");
if (uuid?.value) {
const newExpiration = new Date();
newExpiration.setMinutes(newExpiration.getMinutes() + 15);
const ticketId = "";
sql`
UPDATE basket
SET date = ${newExpiration.toISOString()}
WHERE (uuid =${uuid.value}) AND (ticket_code =${ticketId})
`;
const res = new NextResponse();
res.cookies.set({
name: "uuid",
value: uuid.value,
expires: newExpiration,
});
return res;
}
}Answer