如何在React函数组件路由跳转时复用依赖本地state的常量?
解决方案
方法一:利用Next Router的state传递数据
在Next.js中,useRouter的push方法支持携带额外的state数据,这些数据不会暴露在URL中,刚好能用来传递依赖组件本地state的常量:
原组件(跳转发起方)
import { useRouter } from 'next/router'; import { useState } from 'react'; export default function SourceComponent() { const [superManPowerList, setSuperManPowerList] = useState(['飞行', '热视线']); const [batmanPowerList, setBatmanPowerList] = useState(['高科技装备', '格斗术']); const [wonderWomanPowerList, setWonderWomanPowerList] = useState(['真言套索', '守护银镯']); const superHeroPowers = [ { name: 'Superman', status: superManPowerList }, { name: 'Batman', status: batmanPowerList }, { name: 'Wonder Woman', status: wonderWomanPowerList } ]; const router = useRouter(); const handleNavigate = () => { router.push({ pathname: '/target-component', state: { superHeroPowers } // 将需要传递的常量放进state }); }; return <button onClick={handleNavigate}>跳转到目标组件</button>; }
目标组件(接收方)
import { useRouter } from 'next/router'; export default function TargetComponent() { const router = useRouter(); // 从router.state中取出传递的数据 const superHeroPowers = router.state?.superHeroPowers || []; return ( <div> {superHeroPowers.map(hero => ( <div key={hero.name}> <h3>{hero.name}</h3> <ul> {hero.status.map(power => ( <li key={power}>{power}</li> ))} </ul> </div> ))} </div> ); }
方法二:使用React Context API共享状态
如果这个数据需要在多个组件中复用,推荐用Context API做全局状态管理,避免重复传递:
1. 创建HeroContext
// contexts/HeroContext.tsx import { createContext, useContext, useState, ReactNode } from 'react'; type HeroPower = { name: string; status: string[]; }; type HeroContextType = { superHeroPowers: HeroPower[]; setSuperHeroPowers: (powers: HeroPower[]) => void; }; const HeroContext = createContext<HeroContextType | undefined>(undefined); export function HeroProvider({ children }: { children: ReactNode }) { const [superHeroPowers, setSuperHeroPowers] = useState<HeroPower[]>([]); return ( <HeroContext.Provider value={{ superHeroPowers, setSuperHeroPowers }}> {children} </HeroContext.Provider> ); } export function useHeroContext() { const context = useContext(HeroContext); if (!context) { throw new Error('useHeroContext必须在HeroProvider内部使用'); } return context; }
2. 在_app.tsx中挂载Provider
// pages/_app.tsx import { HeroProvider } from '../contexts/HeroContext'; import type { AppProps } from 'next/app'; export default function App({ Component, pageProps }: AppProps) { return ( <HeroProvider> <Component {...pageProps} /> </HeroProvider> ); }
3. 原组件更新Context状态
import { useState, useEffect } from 'react'; import { useHeroContext } from '../contexts/HeroContext'; import { useRouter } from 'next/router'; export default function SourceComponent() { const [superManPowerList, setSuperManPowerList] = useState(['飞行', '热视线']); const [batmanPowerList, setBatmanPowerList] = useState(['高科技装备', '格斗术']); const [wonderWomanPowerList, setWonderWomanPowerList] = useState(['真言套索', '守护银镯']); const { setSuperHeroPowers } = useHeroContext(); const router = useRouter(); useEffect(() => { // 当本地state变化时,同步更新Context中的数据 const powers = [ { name: 'Superman', status: superManPowerList }, { name: 'Batman', status: batmanPowerList }, { name: 'Wonder Woman', status: wonderWomanPowerList } ]; setSuperHeroPowers(powers); }, [superManPowerList, batmanPowerList, wonderWomanPowerList, setSuperHeroPowers]); const handleNavigate = () => { router.push('/target-component'); }; return <button onClick={handleNavigate}>跳转到目标组件</button>; }
4. 目标组件从Context获取数据
import { useHeroContext } from '../contexts/HeroContext'; export default function TargetComponent() { const { superHeroPowers } = useHeroContext(); return ( <div> {superHeroPowers.map(hero => ( <div key={hero.name}> <h3>{hero.name}</h3> <ul> {hero.status.map(power => ( <li key={power}>{power}</li> ))} </ul> </div> ))} </div> ); }
方法三:使用本地存储(仅适用于可序列化数据)
如果数据都是可序列化的(没有函数、Symbol等特殊类型),可以临时存在localStorage或sessionStorage中:
原组件跳转时存储数据
import { useState } from 'react'; import { useRouter } from 'next/router'; export default function SourceComponent() { const [superManPowerList, setSuperManPowerList] = useState(['飞行', '热视线']); const [batmanPowerList, setBatmanPowerList] = useState(['高科技装备', '格斗术']); const [wonderWomanPowerList, setWonderWomanPowerList] = useState(['真言套索', '守护银镯']); const superHeroPowers = [ { name: 'Superman', status: superManPowerList }, { name: 'Batman', status: batmanPowerList }, { name: 'Wonder Woman', status: wonderWomanPowerList } ]; const router = useRouter(); const handleNavigate = () => { // 转成JSON字符串存入localStorage localStorage.setItem('superHeroPowers', JSON.stringify(superHeroPowers)); router.push('/target-component'); }; return <button onClick={handleNavigate}>跳转到目标组件</button>; }
目标组件读取数据
import { useState, useEffect } from 'react'; export default function TargetComponent() { const [superHeroPowers, setSuperHeroPowers] = useState([]); useEffect(() => { // 读取并解析数据,用完后删除避免残留 const storedData = localStorage.getItem('superHeroPowers'); if (storedData) { setSuperHeroPowers(JSON.parse(storedData)); localStorage.removeItem('superHeroPowers'); } }, []); return ( <div> {superHeroPowers.map(hero => ( <div key={hero.name}> <h3>{hero.name}</h3> <ul> {hero.status.map(power => ( <li key={power}>{power}</li> ))} </ul> </div> ))} </div> ); }
注意:本地存储不适合存放敏感数据,且如果数据包含不可序列化内容会报错。
内容的提问来源于stack exchange,提问作者Mohit Chauhan
相关产品推荐
相关产品推荐

