You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:35:33