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
相关产品推荐
相关产品推荐

