Is there a way to return data and refresh the page with a server action and Next.js
Asked Answered
P

4

6

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,

    });
}
Proficient answered 12/7, 2023 at 13:48 Comment(2)
Does this answer your question?Alyce
@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.Proficient
A
1

For 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 component 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 component 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.

Antechoir answered 14/1 at 12:1 Comment(0)
C
0

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

Coccyx answered 26/10, 2023 at 19:5 Comment(0)
D
0

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')

  }
}
Dufresne answered 5/9 at 9:8 Comment(0)
F
-1

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 component 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 component

Fred answered 12/7, 2023 at 15:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.