Next.js 13中URL传递隐藏数据及刷新保留的实现方案
1. Encrypt and Embed Data in URL Query Params
Your current router.push call excludes query params from the visible URL (the second argument is the plain path), which is why data vanishes on refresh. Instead, encrypt sensitive data and add it as a query param to the URL, then decrypt it on the target page.
Example steps:
- Install a client-side encryption library like
crypto-js - Encrypt data before navigation:
import CryptoJS from 'crypto-js'; const encryptedData = CryptoJS.AES.encrypt(JSON.stringify(data), process.env.NEXT_PUBLIC_ENCRYPTION_KEY).toString(); router.push(`/blog/view/${BlogType}/${blogId}?data=${encryptedData}`); - Decrypt on the target page:
import CryptoJS from 'crypto-js'; const { data } = router.query; if (data) { const decryptedBytes = CryptoJS.AES.decrypt(data, process.env.NEXT_PUBLIC_ENCRYPTION_KEY); const originalData = JSON.parse(decryptedBytes.toString(CryptoJS.enc.Utf8)); // Use the retrieved data }
Note: Store the encryption key in environment variables, and avoid using this method for highly sensitive data (URLs can be logged or shared).
2. Store Data in Cookies or LocalStorage
Save data to client-side storage before navigating, then retrieve it on the target page even after refresh.
LocalStorage (client-side only):
Before navigation:
localStorage.setItem('blogViewData', JSON.stringify(data)); router.push(`/blog/view/${BlogType}/${blogId}`);
On target page (client component):
useEffect(() => { const savedData = localStorage.getItem('blogViewData'); if (savedData) { const originalData = JSON.parse(savedData); // Use the data, then clear it if needed localStorage.removeItem('blogViewData'); } }, []);
Note: LocalStorage isn’t accessible in server components, so this works only for client-rendered pages.
Cookies (server/client accessible):
Use js-cookie to set a cookie before navigation:
import Cookies from 'js-cookie'; Cookies.set('blogViewData', JSON.stringify(data), { expires: 1, secure: process.env.NODE_ENV === 'production' }); router.push(`/blog/view/${BlogType}/${blogId}`);
On target page (server component example):
export async function getServerSideProps(context) { const cookieData = context.req.cookies.blogViewData; let originalData = null; if (cookieData) { originalData = JSON.parse(cookieData); // Clear the cookie after retrieval context.res.setHeader('Set-Cookie', 'blogViewData=; Max-Age=0; Path=/; Secure'); } return { props: { data: originalData } }; }
Note: For sensitive data, add HttpOnly and SameSite flags to enhance security.
3. Server-Side Session Storage
Store data in a server-side session for secure persistence across refreshes.
Using Iron Session (a popular Next.js session library):
- Install
iron-sessionand configure session options in a utility file - Send a POST request to save data to the session before navigation:
await fetch('/api/save-blog-data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); router.push(`/blog/view/${BlogType}/${blogId}`); - Create the API route
/api/save-blog-data.js:import { withIronSessionApiRoute } from 'iron-session/next'; import { sessionOptions } from '../utils/session'; export default withIronSessionApiRoute(async (req, res) => { if (req.method === 'POST') { req.session.blogData = req.body; await req.session.save(); res.status(200).json({ success: true }); } }, sessionOptions); - Retrieve data from the session on the target page (server component):
export async function getServerSideProps(context) { const session = await getIronSession(context.req, context.res, sessionOptions); const blogData = session.blogData; // Clear session data if no longer needed session.blogData = null; await session.save(); return { props: { blogData } }; }
4. Persist Redux State
If you prefer using Redux, add state persistence to survive page refreshes with redux-persist:
- Install
redux-persist - Configure your Redux store with persist middleware:
import { persistStore, persistReducer } from 'redux-persist'; import storage from 'redux-persist/lib/storage'; // Uses localStorage by default const persistConfig = { key: 'root', storage, whitelist: ['blogData'] // Only persist the relevant slice }; const persistedReducer = persistReducer(persistConfig, rootReducer); export const store = configureStore({ reducer: persistedReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false }) }); export const persistor = persistStore(store); - Wrap your app with
PersistGatein_app.js:import { PersistGate } from 'redux-persist/integration/react'; import { store, persistor } from '../store'; function MyApp({ Component, pageProps }) { return ( <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <Component {...pageProps} /> </PersistGate> </Provider> ); }
Redux state will now persist to localStorage and remain after refresh.
5. Fetch Data Directly in Server Components (App Router)
If using Next.js 13’s App Router, skip passing data via navigation entirely. Fetch the required data directly in the target server component using the blogId from the URL:
// app/blog/view/[blogType]/[blogId]/page.js export default async function BlogViewPage({ params }) { const blogData = await fetch(`https://your-api.com/blogs/${params.blogId}`).then(res => res.json()); return <div>{/* Render content using blogData */}</div>; }
This method ensures data is fetched fresh on every load (including refresh) without relying on client-side state or URL params.
内容的提问来源于stack exchange,提问作者Thari Raw

