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函数,并在其中附带跳转状态:
- 从
react-router-dom导入redirect函数 - 请求成功后,返回
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
相关产品推荐
相关产品推荐

