I'm trying to create a webapp with Next.js (13.4.9) and I would use the server action. With the server action, I would send data to my action, this action is going to treat this data and return me a string. The only way I've found so far to get the result data from the action is with the cookies. So is there an other way (easier) I can get the data from the server action ? And I would also refresh the page or redirect the user to an other page just after the server action (like with php). So how can I do a refreshing or a redirect after the server action ?
Here is my actual code :
// page.tsx
"use client";
import React, { useTransition, useState } from "react";
import { SendTicket } from "@/actions/TicketAction";
import Cookies from "js-cookie";
export default function TicketPage(){
const [isPending, startTransition] = useTransition();
const [ name, setName ] = useState<string>("");
const [ age, setAge ] = useState<number>(0);
return(
<main>
<form action={() => startTransition(() => SendTicket({
name: name, age: age
}))}>
<input type="text" value={name} onChange={(e) => setName(e.target.value)}
placeholder="Your name" />
<input type="number" value={age} onChange={(e) => setAge(parseInt(e.target.value))}
placeholder="Your age" />
<button type="submit">
Valider
</button>
</form>
{ isPending ? <span>Loading...</span> : <></> }
<Result />
</main>
)
}
function Result(){
const ResultString = Cookies.get("ResultString");
Cookies.remove("ResultString");
return(
<p>{ResultString?.toString()}</p>
)
}
// TicketAction.ts
"use server";
import { cookies } from "next/headers";
export interface TicketInformationProps {
name: string;
age: number;
}
export async function SendTicket(TicketInforamtion: TicketInformationProps){
console.log(`[NEW TICKET]`);
console.log(`Nom: ${TicketInforamtion.name}`);
console.log(`Age: ${TicketInforamtion.age.toString()}`);
console.log(`\n\n\n`);
const result = `You are ${TicketInforamtion.name} and you are ${TicketInforamtion.age.toString()} yo.`;
cookies().set({
name: "ResultString",
value: result,
path: "/ticket",
expires: new Date(Date.now() + 1000 * 1),
secure: true,
});
}
I'm trying to create a webapp with Next.js (13.4.9) and I would use the server action. With the server action, I would send data to my action, this action is going to treat this data and return me a string. The only way I've found so far to get the result data from the action is with the cookies. So is there an other way (easier) I can get the data from the server action ? And I would also refresh the page or redirect the user to an other page just after the server action (like with php). So how can I do a refreshing or a redirect after the server action ?
Here is my actual code :
// page.tsx
"use client";
import React, { useTransition, useState } from "react";
import { SendTicket } from "@/actions/TicketAction";
import Cookies from "js-cookie";
export default function TicketPage(){
const [isPending, startTransition] = useTransition();
const [ name, setName ] = useState<string>("");
const [ age, setAge ] = useState<number>(0);
return(
<main>
<form action={() => startTransition(() => SendTicket({
name: name, age: age
}))}>
<input type="text" value={name} onChange={(e) => setName(e.target.value)}
placeholder="Your name" />
<input type="number" value={age} onChange={(e) => setAge(parseInt(e.target.value))}
placeholder="Your age" />
<button type="submit">
Valider
</button>
</form>
{ isPending ? <span>Loading...</span> : <></> }
<Result />
</main>
)
}
function Result(){
const ResultString = Cookies.get("ResultString");
Cookies.remove("ResultString");
return(
<p>{ResultString?.toString()}</p>
)
}
// TicketAction.ts
"use server";
import { cookies } from "next/headers";
export interface TicketInformationProps {
name: string;
age: number;
}
export async function SendTicket(TicketInforamtion: TicketInformationProps){
console.log(`[NEW TICKET]`);
console.log(`Nom: ${TicketInforamtion.name}`);
console.log(`Age: ${TicketInforamtion.age.toString()}`);
console.log(`\n\n\n`);
const result = `You are ${TicketInforamtion.name} and you are ${TicketInforamtion.age.toString()} yo.`;
cookies().set({
name: "ResultString",
value: result,
path: "/ticket",
expires: new Date(Date.now() + 1000 * 1),
secure: true,
});
}
Share
Improve this question
asked Jul 12, 2023 at 13:48
raffgiga21raffgiga21
1781 gold badge2 silver badges9 bronze badges
2
- Does this answer your question? – Fabio Nettis Commented Jul 12, 2023 at 14:01
- @FabioNettis I have just been trying but it doesn't seem working with the server actions. It doesn't redirect the user on the other path. – raffgiga21 Commented Jul 12, 2023 at 14:19
4 Answers
Reset to default 1For Next.js v.14:
You have to use useFormState()
hook and after mutating the data in your action server and return an object which will cause the ponent that sent the form data to rerender (it's like a refresh).
Note: You have to use revalidatePath('/')
after mutating the data to tell Next.js that the ponent that sent the form data is a dynamic page so it will re-render on new requests (when it will re-render because of useFormState hook) instead of serving a cached version of the page.
You can get the return data as follows:
import { experimental_useFormState as useFormState } from 'react-dom'
...
const [state, formAction] = useFormState(action);
...
Where state will be undefined (or optionally set to an initial value) until a return value is received from the server action
I am not sure if it's still relevant, I am using "try catch and finally" which served my needs maybe you can try something like this:
export const myAction = async () =>
{
try {
const { data, error } = await getData()
if (!error) throw new Error("Error")
return { data }
} catch (error) {
console.log({ error })
throw new Error("Couldn't login")
} finally {
redirect('/anywhere')
}
}
server actions are still experimental. you should have this setup in next.config.js
const nextConfig = {
experimental: {
serverActions: true,
},
};
"use server" directive should be placed at the top of the ponent function body.
// this will refresh
import { revalidatePath } from "next/cache";
export async function SendTicket(TicketInforamtion: TicketInformationProps){
const result = `You are ${TicketInforamtion.name} and you are ${TicketInforamtion.age.toString()} yo.`;
"use server"
cookies().set({
name: "ResultString",
value: result,
path: "/ticket",
expires: new Date(Date.now() + 1000 * 1),
secure: true,
});
revalidatePath("/route");
}
server actions are used to mutate data on the server or do server specific tasks. I do not think that you can have a return value and use it inside the ponent