skip to Main Content

In Remix, how do you return json first and then redirect after a success call on the API?

export const action: ActionFunction = async ({
    request,
}: ActionFunctionArgs) => {
    const formData = await request.formData();

    try {
        const { project } = await sampleAPICall(formData);
        return json({
            title: "Success",
            message: "Yehey!",
        });

        throw redirect(`/${project?.id}`); 
    } catch (error) {
        return json({
            variant: "destructive",
            message: "Oh no....",
        });
    }
};

2

Answers


  1. I think you need to structure your code to handle the redirection separately from the JSON response. You cannot have code that executes after a return statement.

    export const action: ActionFunction = async ({
        request,
        redirect,
    }: ActionFunctionArgs) => {
        const formData = await request.formData();
    
        try {
            const { project } = await sampleAPICall(formData);
            return json({
                title: "Success",
                message: "Yehey!",
                redirectTo: `/${project?.id}`, // Include redirection URL in JSON response
            });
        } catch (error) {
            return json({
                variant: "destructive",
                message: "Oh no....",
            });
        }
    };
    
    export const loader: LoaderFunction = ({ json }) => {
        return json();
    };
    
    

    Hopefully I was able to help! Best of luck! 🙂

    Login or Signup to reply.
  2. Redirects can’t have a body, so you can’t include a JSON payload in a redirect. If you want to display a message on the redirected route, you would typically use session flash.

    https://remix.run/docs/en/main/utils/sessions#sessionflashkey-value

    import { commitSession, getSession } from "../sessions";
    
    export async function action({
      params,
      request,
    }: ActionFunctionArgs) {
      const session = await getSession(request.headers.get("Cookie"));
      const formData = await request.formData;
      const { project } = await sampleAPICall(formData);
      session.flash("message", { title: "Success", message: "Yehey!" });
    
      return redirect("`/${project?.id}`, {
        headers: {
          "Set-Cookie": await commitSession(session),
        },
      });
    }
    

    Then in your project route, you can display the message from flash

    import { json } from "@remix-run/node";
    import { useLoaderData } from "@remix-run/react";
    import { getSession, commitSession } from "./sessions";
    
    export async function loader({ request } LoaderFunctionArgs) {
      const session = await getSession(request.headers.get("Cookie"));
      const message = session.get("message") || null;
    
      return json(
        { message },
        {
          headers: {
            // only necessary with cookieSessionStorage
            "Set-Cookie": await commitSession(session),
          },
        }
      );
    }
    
    export default function Component() {
      const { message } = useLoaderData<typeof loader>();
    
      return (
        <div>
          {message ? (
            <div className="flash">{message.title} {message.message}</div>
          ) : null}
        </div>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search