NextJS 14中使用router.push无URL直接传对象的问题求助
Next.js 14 不通过URL传递数据的解决方案
你遇到的问题核心是:App Router 中的 next/navigation 模块里,router.push 的第二个参数没有 query 选项,且 useSearchParams 只能读取URL上的显式查询参数,所以你之前的写法无法拿到数据。下面是几种无需通过URL传递对象的可行方案:
方案1:使用路由自带的 state 参数(最直接)
这是Next.js App Router原生支持的临时数据传递方式,数据不会出现在URL中,仅存在于会话内存中(页面刷新后会丢失)。
Page1 跳转代码
import { useRouter } from 'next/navigation'; // ... const router = useRouter(); router.push( `/restaurant/${params.uniqueValue}/checkout/order/${newOrder.data.orderNumber}`, { state: { test: "test", orderData: newOrder.data // 直接传递对象 } } );
Page2 读取数据代码
import { useRouter } from 'next/navigation'; const router = useRouter(); const routeState = router.state; console.log(routeState?.test); // 输出 "test" console.log(routeState?.orderData); // 输出你的订单对象
方案2:React Context 全局状态共享
适合需要在多个页面、组件间共享数据的场景,数据会在页面刷新后保留(取决于你是否做持久化)。
1. 创建Context文件
// app/context/OrderContext.js 'use client'; import { createContext, useContext, useState } from 'react'; const OrderContext = createContext(); export function OrderProvider({ children }) { const [orderData, setOrderData] = useState(null); return ( <OrderContext.Provider value={{ orderData, setOrderData }}> {children} </OrderContext.Provider> ); } export function useOrderContext() { return useContext(OrderContext); }
2. 在根Layout中包裹Provider
// app/layout.js import { OrderProvider } from './context/OrderContext'; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body> <OrderProvider>{children}</OrderProvider> </body> </html> ); }
3. Page1 设置数据并跳转
import { useOrderContext } from '../context/OrderContext'; import { useRouter } from 'next/navigation'; const Page1 = () => { const { setOrderData } = useOrderContext(); const router = useRouter(); const handleNavigate = () => { setOrderData({ test: "test", orderNumber: newOrder.data.orderNumber }); router.push(`/restaurant/${params.uniqueValue}/checkout/order/${newOrder.data.orderNumber}`); }; return <button onClick={handleNavigate}>跳转到结算页</button>; };
4. Page2 读取数据
import { useOrderContext } from '../context/OrderContext'; const Page2 = () => { const { orderData } = useOrderContext(); console.log(orderData?.test); // 输出 "test" return <div>订单号:{orderData?.orderNumber}</div>; };
方案3:LocalStorage/SessionStorage 本地存储
适合需要持久化数据,或跨会话传递的场景(注意:敏感数据不要存在本地,有安全风险)。
Page1 存储数据并跳转
import { useRouter } from 'next/navigation'; const router = useRouter(); const handleNavigate = () => { // 将对象转为JSON字符串存储 localStorage.setItem('orderData', JSON.stringify({ test: "test", orderNumber: newOrder.data.orderNumber })); router.push(`/restaurant/${params.uniqueValue}/checkout/order/${newOrder.data.orderNumber}`); };
Page2 读取数据
'use client'; import { useEffect, useState } from 'react'; const Page2 = () => { const [orderData, setOrderData] = useState(null); useEffect(() => { const storedData = localStorage.getItem('orderData'); if (storedData) { setOrderData(JSON.parse(storedData)); // 读取后建议删除,避免数据残留 localStorage.removeItem('orderData'); } }, []); console.log(orderData?.test); return <div>订单号:{orderData?.orderNumber}</div>; };
各方案适用场景
- 路由State:临时跳转传数据,简单直接,页面刷新后数据丢失。
- React Context:多页面/组件共享全局状态,数据持久化可控。
- LocalStorage:跨会话传递数据,适合非敏感信息的持久化存储。
内容的提问来源于stack exchange,提问作者Poumon
相关产品推荐
相关产品推荐

