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

如何通过React Router向新组件传递对象或ID?及路由错误处理

解决React Router路由传参+Firebase数据传递问题

先给你解决眼前的警告错误,再讲两种实现数据传递的靠谱方案:

首先修复组件类型警告

你看到的Warning: Failed prop type: Invalid prop component of type object supplied to Route, expected function,原因有三个:

  1. React组件名必须首字母大写:你的question组件要改成Question(比如import Question from './Question'),否则React会把它当成普通HTML标签,而非自定义组件。
  2. Route的component属性要传组件定义:确保传给Route的是组件本身(v6用element={<Question />},v5用component={Question}),不是组件实例或其他对象。
  3. Link的路径格式错误:你写的to={questions/:${question.id}}里的冒号是Route用来定义参数占位符的,Link里要传实际ID值,正确写法是to={/questions/${question.id}}。

方案一:通过URL参数ID重新查询Firebase

这是最稳妥的方式(即使用户直接刷新页面也能正常加载),步骤如下:

1. 配置路由和跳转链接

import { BrowserRouter as Router, Link, Routes, Route } from 'react-router-dom';
import Question from './Question'; // 确保组件首字母大写

// 在你的问题列表组件中:
<Router>
  {/* 生成带实际ID的跳转链接 */}
  <Link 
    to={`/questions/${question.id}`} 
    style={{display: 'block', margin: 'auto'}}
  >
    Rozwiaz to zadanie kurwo
  </Link>

  {/* 用Routes包裹路由规则(v6写法,v5用Switch) */}
  <Routes>
    <Route path="/questions/:id" element={<Question />} />
  </Routes>
</Router>

2. 在目标组件中通过ID查询Firebase

在Question组件里,用useParams提取URL中的ID,再调用Firebase API查询对应数据:

import { useParams, useEffect, useState } from 'react';
import { db } from './firebaseConfig'; // 你的Firebase配置文件
import { doc, getDoc } from 'firebase/firestore';

function Question() {
  const { id } = useParams(); // 提取URL中的id参数
  const [questionData, setQuestionData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 定义异步查询函数
    const fetchQuestion = async () => {
      try {
        // 假设你的问题数据存在名为"questions"的Firestore集合中
        const docRef = doc(db, 'questions', id);
        const docSnap = await getDoc(docRef);

        if (docSnap.exists()) {
          setQuestionData(docSnap.data());
        } else {
          console.log("找不到对应的问题文档!");
        }
      } catch (err) {
        console.error("查询数据出错:", err);
      } finally {
        setLoading(false);
      }
    };

    // 当ID存在时执行查询
    if (id) fetchQuestion();
  }, [id]); // ID变化时重新触发查询

  if (loading) return <div>加载中...</div>;
  if (!questionData) return <div>未找到该问题</div>;

  // 渲染问题内容
  return (
    <div>
      <h2>{questionData.title}</h2>
      <p>{questionData.content}</p>
      {/* 其他问题相关内容 */}
    </div>
  );
}

export default Question;

方案二:直接传递整个问题对象(无需重复查询)

如果已经在列表页拿到了完整的问题数据,不想再调用Firebase接口,可以用React Router的state属性传递对象:

1. 修改Link的跳转逻辑

<Link 
  to={{
    pathname: `/questions/${question.id}`,
    state: { question: question } // 把整个问题对象存入路由state
  }}
  style={{display: 'block', margin: 'auto'}}
>
  Rozwiaz to zadanie kurwo
</Link>

2. 在目标组件中获取state数据

import { useLocation, useParams } from 'react-router-dom';

function Question() {
  const location = useLocation();
  const { id } = useParams();
  // 从路由state中取出问题数据,加可选链防止state不存在
  const questionData = location.state?.question;

  // 处理用户直接刷新页面的情况(此时state会丢失,建议 fallback 到方案一的查询逻辑)
  if (!questionData) {
    return <div>加载中...</div>;
    // 或者这里可以写跳转回列表页的逻辑,或者启动ID查询
  }

  return (
    <div>
      <h2>{questionData.title}</h2>
      <p>{questionData.content}</p>
      {/* 其他问题内容 */}
    </div>
  );
}

注意事项

  • 如果使用state传对象,用户刷新页面后state会丢失,所以一定要加fallback逻辑(比如用ID重新查询)。
  • 确认你的React Router版本:上面的代码是v6的写法,如果是v5的话,Route要用component={Question}代替element={<Question />},且用Switch包裹Route。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:22:27