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

状态变更后如何通过React Router向React组件传递props?

问题描述

我正在构建一个Web应用,其中包含一个带有多个score的下拉列表,每个score的代码如下:

<NavDropdown.Item 
  key = {i}
  id = {score["scoreId"]}
  onClick = {(e) => {
    setScore(score)
    window.location.href = '/home/score'
    // do something to go to the score page
  }}
>
  {score["scoreName"]}
</NavDropdown.Item>

点击score时,我先使用setScore()将score状态设置为当前选中的score,然后跳转到/home/score页面,路由配置如下:

<Routes>
  <Route path="/score" element={<ScoreHome score={score}/>} />
</Routes>

遇到的问题:我需要将新设置的score传递给<ScoreHome />组件,但useState()是异步的,导致新页面的props.score为undefined。

我尝试用useEffect处理:

useEffect(() => {
  window.location.href = '/home/score'
},[score])

但这会造成无限循环(浏览器持续跳转或刷新/home/score页面),请问最佳解决方法是什么?

最佳解决方法

方案1:通过路由参数传递scoreId,在目标页面获取完整数据

这是最可靠的方案,完全避开前端状态异步的问题:

  1. 修改下拉项的点击事件,跳转到带scoreId参数的路由:
<NavDropdown.Item 
  key={i}
  id={score["scoreId"]}
  onClick={(e) => {
    window.location.href = `/home/score?scoreId=${score["scoreId"]}`
  }}
>
  {score["scoreName"]}
</NavDropdown.Item>
  1. 在ScoreHome组件中,通过useSearchParams获取参数,再根据scoreId获取对应的score数据:
import { useSearchParams } from 'react-router-dom';

function ScoreHome() {
  const [searchParams] = useSearchParams();
  const scoreId = searchParams.get('scoreId');
  
  const [score, setScore] = useState(null);
  
  useEffect(() => {
    if (scoreId) {
      // 可通过接口请求数据,或从本地数据源中查找
      const targetScore = scoreList.find(item => item.scoreId === scoreId);
      setScore(targetScore);
    }
  }, [scoreId]);
  
  if (!score) return <div>加载中...</div>;
  
  return (
    {/* 渲染score内容 */}
  );
}

方案2:用React Router的navigate方法携带state

如果不想在URL中暴露参数,可以用这种方式传递数据:

  1. 在当前组件中引入并初始化useNavigate:
import { useNavigate } from 'react-router-dom';

const navigate = useNavigate();
  1. 修改下拉项的点击事件:
<NavDropdown.Item 
  key={i}
  id={score["scoreId"]}
  onClick={(e) => {
    navigate('/home/score', { state: { score: score } });
  }}
>
  {score["scoreName"]}
</NavDropdown.Item>
  1. 在ScoreHome组件中通过useLocation获取传递的state:
import { useLocation } from 'react-router-dom';

function ScoreHome() {
  const location = useLocation();
  const score = location.state?.score;
  
  if (!score) return <div>无有效数据</div>;
  
  return (
    {/* 渲染score内容 */}
  );
}

方案3:使用全局状态管理(Context API/Redux)

如果应用中多个组件需要共享score状态,可采用全局状态方案:

  1. 创建ScoreContext:
import { createContext, useContext, useState } from 'react';

const ScoreContext = createContext();

export function ScoreProvider({ children }) {
  const [currentScore, setCurrentScore] = useState(null);
  
  return (
    <ScoreContext.Provider value={{ currentScore, setCurrentScore }}>
      {children}
    </ScoreContext.Provider>
  );
}

export function useScore() {
  return useContext(ScoreContext);
}
  1. 在根组件中用ScoreProvider包裹路由:
<ScoreProvider>
  <Routes>
    <Route path="/score" element={<ScoreHome />} />
  </Routes>
</ScoreProvider>
  1. 修改下拉项的点击事件:
import { useScore } from './ScoreContext';

const { setCurrentScore } = useScore();

<NavDropdown.Item 
  key={i}
  id={score["scoreId"]}
  onClick={(e) => {
    setCurrentScore(score);
    window.location.href = '/home/score';
  }}
>
  {score["scoreName"]}
</NavDropdown.Item>
  1. 在ScoreHome组件中获取全局状态:
import { useScore } from './ScoreContext';

function ScoreHome() {
  const { currentScore } = useScore();
  
  if (!currentScore) return <div>无有效数据</div>;
  
  return (
    {/* 渲染score内容 */}
  );
}

关于之前的无限循环问题

跳转后组件重新渲染,score状态的变化会再次触发useEffect的执行,进而再次跳转,形成循环,所以这种方式不可行。

内容的提问来源于stack exchange,提问作者Nathan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:15:41