You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Remix中如何先返回json再在API调用成功后执行redirect?

在Remix中实现API成功后先返回JSON再跳转的方案

原代码里return json(...)之后的throw redirect(...)永远不会执行,因为return语句会直接终止函数运行。而且HTTP协议规定一个请求只能返回一种响应(要么是JSON数据,要么是重定向指令),没法同时返回两者。要实现需求,得换思路从客户端或结合Session处理。

方案一:客户端处理跳转(推荐)

在服务端的action只返回成功JSON和跳转地址,由客户端组件接收响应后执行跳转。

Action代码修改:

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

  try {
    const { project } = await sampleAPICall(formData);
    // 返回成功信息和跳转目标地址
    return json({
      title: "Success",
      message: "Yehey!",
      redirectTo: `/${project?.id}`
    });
  } catch (error) {
    return json(
      {
        variant: "destructive",
        message: "Oh no....",
      },
      { status: 400 } // 给错误响应加上状态码,方便客户端识别
    );
  }
};

客户端组件代码:

import { useActionData, useNavigate } from "@remix-run/react";
import { useEffect } from "react";

export default function YourFormComponent() {
  const actionData = useActionData<typeof action>();
  const navigate = useNavigate();

  // 监听action返回数据,有跳转地址就执行跳转
  useEffect(() => {
    if (actionData?.redirectTo) {
      navigate(actionData.redirectTo);
    }
  }, [actionData, navigate]);

  return (
    <form method="post">
      {/* 你的表单元素 */}
      <button type="submit">提交</button>
      {/* 可选择显示成功提示 */}
      {actionData?.title && (
        <div className="success-notice">
          {actionData.title}: {actionData.message}
        </div>
      )}
    </form>
  );
}

方案二:服务端重定向+Session闪存消息

如果不需要先返回JSON再跳转,而是希望跳转后展示成功提示,可以用Remix的Session闪存消息(Flash Message),把提示存在Session里,跳转后再取出显示。

Action代码:

import { redirect, json } from "@remix-run/node";
// 假设你已经配置好了Session服务,路径根据你的项目调整
import { getSession, commitSession } from "~/services/session.server";

export const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
  const formData = await request.formData();
  const session = await getSession(request.headers.get("Cookie"));

  try {
    const { project } = await sampleAPICall(formData);
    // 把成功消息存入Session闪存(刷新页面后自动清除)
    session.flash("successMsg", {
      title: "Success",
      message: "Yehey!"
    });
    // 重定向到目标页面,同时提交Session
    return redirect(`/${project?.id}`, {
      headers: {
        "Set-Cookie": await commitSession(session)
      }
    });
  } catch (error) {
    session.flash("errorMsg", {
      variant: "destructive",
      message: "Oh no...."
    });
    // 重定向回原页面显示错误
    return redirect(request.url, {
      headers: {
        "Set-Cookie": await commitSession(session)
      }
    });
  }
};

跳转后的页面(示例:项目详情页):

import { useLoaderData } from "@remix-run/react";
import { getSession } from "~/services/session.server";

export const loader = async ({ request }) => {
  const session = await getSession(request.headers.get("Cookie"));
  // 取出Session里的成功消息
  const successMsg = session.get("successMsg");
  return json({ successMsg });
};

export default function ProjectDetailPage() {
  const { successMsg } = useLoaderData<typeof loader>();

  return (
    <div>
      {/* 显示成功提示 */}
      {successMsg && (
        <div className="success-alert">
          {successMsg.title}: {successMsg.message}
        </div>
      )}
      {/* 项目详情内容 */}
      <h1>项目详情</h1>
      {/* ...其他内容 */}
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Joseph

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 13:53:35