在Next.js的getInitialProps中如何实现重定向并传递数据
解决方案
方案1:小数据量使用查询参数传递(兼容性最好,服务端/客户端跳转都支持)
适合数据体积小、非敏感的场景,直接把序列化后的数据拼到跳转路径的查询参数中即可,代码改动如下:
import "styles/globals.css"; import React, { useEffect } from "react"; import axios from "axios"; import Router from "next/router"; export const MyContext= React.createContext({}); function MyApp({ Component, pageProps, data, redirect }) { // 客户端检测跳转参数执行跳转 useEffect(() => { if (redirect) { Router.push(redirect) } }, [redirect]) return ( <MyContext.Provider value={data}> <Component {...pageProps} /> </MyContext.Provider> ); } MyApp.getInitialProps = async (context) => { if (context.ctx.pathname !== "/") { return {}; } const id= context.ctx.query.id; try { const url = `http://somepage.com/${id}`; const res = await axios.get(url); const data = res.data; if (data.hasSomeValue) { // 序列化数据拼到跳转路径 const serializedData = encodeURIComponent(JSON.stringify(data)) const redirectPath = `/success?data=${serializedData}` // 服务端环境直接执行302跳转 if (context.ctx.res) { context.ctx.res.writeHead(302, { Location: redirectPath }) context.ctx.res.end() return {} } return { data: data, redirect: redirectPath, }; } return { data }; } catch (e) { const redirectPath = "/error" if (context.ctx.res) { context.ctx.res.writeHead(302, { Location: redirectPath }) context.ctx.res.end() return {} } return { redirect: redirectPath, }; } }; export default MyApp;
目标页面拿到参数后反序列化即可使用:
// /success页面代码示例 const SuccessPage = ({ query }) => { const data = JSON.parse(decodeURIComponent(query.data)) // 后续业务逻辑 } SuccessPage.getInitialProps = async ({ query }) => { return { query } }
方案2:大数据量使用全局Context传递(不会暴露数据在地址栏)
你已经定义了全局的MyContext上下文,跳转时数据会保留在上下文里,跳转后的页面直接消费上下文就能拿到数据,适合数据量大、不想暴露数据在地址栏的客户端跳转场景,代码改动如下:
import "styles/globals.css"; import React, { useEffect } from "react"; import axios from "axios"; import Router from "next/router"; export const MyContext= React.createContext({}); function MyApp({ Component, pageProps, data, redirect }) { useEffect(() => { if (redirect) { Router.push(redirect) } }, [redirect]) // 跳转后数据依然保存在Provider中,目标页面可直接消费 return ( <MyContext.Provider value={data}> <Component {...pageProps} /> </MyContext.Provider> ); } MyApp.getInitialProps = async (context) => { // 服务端跳转场景下Context会重置,不适用该方案,建议用方案1 if (context.ctx.res) return {} if (context.ctx.pathname !== "/") { return {}; } const id= context.ctx.query.id; try { const url = `http://somepage.com/${id}`; const res = await axios.get(url); const data = res.data; if (data.hasSomeValue) { return { data: data, redirect: "/success", }; } return { data }; } catch (e) { return { data: { error: e.message }, redirect: "/error", }; } }; export default MyApp;
目标页面直接消费上下文拿数据:
// /success页面代码示例 import { MyContext } from './_app' const SuccessPage = () => { const data = React.useContext(MyContext) // 后续业务逻辑 }
注意事项
- 如果你使用的是 Next.js 13+ App Router 版本,更推荐用
next/navigation提供的redirect方法配合 cookies 或者 searchParams 传递数据 - 敏感数据不要通过 URL Query 传递,会暴露在地址栏和浏览历史记录中
- 服务端跳转场景下全局 Context 会被重置,该场景优先使用方案 1 或者服务端临时存储(如 session)传递数据
内容的提问来源于stack exchange,提问作者goscamp
相关产品推荐
相关产品推荐

