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

react-router-dom v6中如何在action内带状态导航至BillRender组件

问题描述

我想在BillRender.tsx组件中加载跳转状态,但使用react-router-dom v6的Navigate(带状态)功能时遇到两个问题:

  • 从action中返回Navigate组件无法实现渲染
  • 无法在异步的billAction.tsx函数中调用useNavigate钩子

如果只是无数据跳转我会用redirect,但现在需要传递状态。

相关代码

actions/billAction.tsx

import api from "../utils/api";

export default async function({ request }: { request: any }) {
  try {
    const formData = await request.formData();
    const data : { [key: string]: string } = Object.fromEntries(formData);
    let items : { [key: string]: { [key: string]: number } } = {};

    const clientName = data.clientName;

    for (const key in data) {
      const value = data[key];

      if (key !== "clientName" && value !== "") {
        const [type, id] = key.split("-");
        if (!items[id]) {
          items[id] = {};
        }
        items[id][type] = parseInt(value);
      }
    }

    const itemsArray = Object.entries(items).map(([key, value]) => ({
      _id: key,
      ...value
    }));

    const response = await api.post("/bill", { clientName: clientName, products: itemsArray });
    // where to call useNavigate() hook?
    // navigate("/bill/render", { state: { bill: response.data } });
  } catch (error) {
    console.log(error);
    return error;
  }
}

components/BillRender.tsx

import { useLocation } from "react-router-dom";
import { useEffect } from "react";

export default function(){
  const location = useLocation();
  const bill = location.state.bill;
  console.log(bill);

  useEffect(() => {
    const billDiv = document.getElementById("bill");
    if (billDiv) {
      billDiv.innerHTML = bill;
    }
  }, [bill]);

  return (
    <div id="bill">
    </div>
  );
}
解决方案

在react-router-dom v6.4+的路由action中,不能直接调用useNavigate钩子(钩子仅允许在React组件或自定义钩子中使用),也不能直接返回Navigate组件。正确的做法是使用路由提供的redirect函数,并在其中附带跳转状态:

  1. 从react-router-dom导入redirect函数
  2. 请求成功后,返回redirect并传入目标路径和状态数据

修改后的billAction.tsx代码如下:

import api from "../utils/api";
import { redirect } from "react-router-dom"; // 导入redirect

export default async function({ request }: { request: any }) {
  try {
    const formData = await request.formData();
    const data : { [key: string]: string } = Object.fromEntries(formData);
    let items : { [key: string]: { [key: string]: number } } = {};

    const clientName = data.clientName;

    for (const key in data) {
      const value = data[key];

      if (key !== "clientName" && value !== "") {
        const [type, id] = key.split("-");
        if (!items[id]) {
          items[id] = {};
        }
        items[id][type] = parseInt(value);
      }
    }

    const itemsArray = Object.entries(items).map(([key, value]) => ({
      _id: key,
      ...value
    }));

    const response = await api.post("/bill", { clientName: clientName, products: itemsArray });
    
    // 使用redirect并传递状态
    return redirect({
      pathname: "/bill/render",
      state: { bill: response.data }
    });
  } catch (error) {
    console.log(error);
    return error;
  }
}

你的BillRender.tsx代码无需修改,依然可以通过useLocation()获取跳转带来的状态数据。

注意:确保你的路由配置使用createBrowserRouter或类似的v6.4+路由API,这样action才能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:02:46