Next.js 13 App Router中,router.push跳转后如何复用前页数据?
几种优化Next.js 13 App Router中测验结果传递的方案
1. 通过router.push传递查询参数(适合小体量非敏感数据)
如果结果数据量不大且不涉及敏感信息,可以直接在跳转时把数据附在URL的查询参数里,避免二次请求数据库。
在/quiz页面提交后:
import { useRouter } from 'next/navigation'; const QuizPage = () => { const router = useRouter(); const handleSubmit = async () => { // 提交结果到数据库,拿到返回的结果数据或ID const result = await saveResultToDB(quizAnswers); // 直接传递结果数据(数据量小时适用) router.push(`/results?score=${result.score}&total=${result.total}`); // 或者传递结果ID(后续用ID做精准查询,比全量查询高效) // router.push(`/results?resultId=${result.id}`); }; };
在/results页面获取参数:
import { useSearchParams } from 'next/navigation'; const ResultsPage = () => { const searchParams = useSearchParams(); const score = searchParams.get('score'); const total = searchParams.get('total'); return ( <div> <p>你的得分:{score}/{total}</p> </div> ); };
注意:敏感数据不要用这种方式,URL会暴露内容。
2. 使用React Context共享状态
在App Router的根layout中提供全局Context,临时存储测验结果,跳转后/results页面直接读取即可。
首先创建Context:
// app/context/ResultContext.js 'use client'; import { createContext, useContext, useState } from 'react'; const ResultContext = createContext(); export const ResultProvider = ({ children }) => { const [quizResult, setQuizResult] = useState(null); return ( <ResultContext.Provider value={{ quizResult, setQuizResult }}> {children} </ResultContext.Provider> ); }; export const useResultContext = () => useContext(ResultContext);
在根layout中引入Provider:
// app/layout.js import { ResultProvider } from './context/ResultContext'; export default function RootLayout({ children }) { return ( <html lang="zh-CN"> <body> <ResultProvider>{children}</ResultProvider> </body> </html> ); }
在/quiz页面存储结果:
'use client'; import { useRouter } from 'next/navigation'; import { useResultContext } from '../context/ResultContext'; const QuizPage = () => { const router = useRouter(); const { setQuizResult } = useResultContext(); const handleSubmit = async () => { const result = await saveResultToDB(quizAnswers); // 把结果存入Context setQuizResult(result); router.push('/results'); }; };
在/results页面读取结果:
'use client'; import { useResultContext } from '../context/ResultContext'; const ResultsPage = () => { const { quizResult } = useResultContext(); if (!quizResult) { return <div>加载中...</div>; } return ( <div> <h2>测验结果</h2> <p>得分:{quizResult.score}/{quizResult.total}</p> {/* 展示其他结果内容 */} </div> ); };
3. 利用TanStack Query的缓存机制
如果已经在用TanStack Query(React Query),可以在提交结果的mutation完成后缓存数据,/results页面直接读取缓存,无需额外请求。
在/quiz页面提交并缓存:
'use client'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useRouter } from 'next/navigation'; const QuizPage = () => { const router = useRouter(); const queryClient = useQueryClient(); const saveResultMutation = useMutation({ mutationFn: saveResultToDB, onSuccess: (result) => { // 把结果缓存起来,指定唯一key queryClient.setQueryData(['quiz-result'], result); router.push('/results'); }, }); const handleSubmit = () => { saveResultMutation.mutate(quizAnswers); }; };
在/results页面读取缓存:
'use client'; import { useQuery } from '@tanstack/react-query'; const ResultsPage = () => { // 读取缓存的数据,无需发送实际请求 const { data: quizResult } = useQuery({ queryKey: ['quiz-result'], queryFn: () => null, initialData: () => queryClient.getQueryData(['quiz-result']), }); if (!quizResult) { return <div>请先完成测验</div>; } return ( <div> <h2>测验结果</h2> <p>得分:{quizResult.score}/{quizResult.total}</p> </div> ); };
4. 使用localStorage临时存储(非敏感数据)
如果数据不敏感,提交后把结果存在localStorage,跳转后读取,用完再清除。
在/quiz页面:
'use client'; import { useRouter } from 'next/navigation'; const QuizPage = () => { const router = useRouter(); const handleSubmit = async () => { const result = await saveResultToDB(quizAnswers); localStorage.setItem('quiz-result', JSON.stringify(result)); router.push('/results'); }; };
在/results页面:
'use client'; import { useEffect, useState } from 'react'; const ResultsPage = () => { const [quizResult, setQuizResult] = useState(null); useEffect(() => { const storedResult = localStorage.getItem('quiz-result'); if (storedResult) { setQuizResult(JSON.parse(storedResult)); // 读取后清除,避免下次进入页面残留数据 localStorage.removeItem('quiz-result'); } }, []); if (!quizResult) { return <div>加载中...</div>; } return ( <div> <h2>测验结果</h2> <p>得分:{quizResult.score}/{quizResult.total}</p> </div> ); };
内容的提问来源于stack exchange,提问作者esafresa
相关产品推荐
相关产品推荐

