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

如何在多页面展示Firebase Cloud Firestore数据并实现React页面间的数据传递

如何将Firestore的政客数据从列表页传递到详情页?

先看你的需求:点击列表页的政客卡片后,要把对应政客的真实Firestore数据展示在详情页里,不需要导入整个Polis组件,只需要复用Firebase配置或部分查询逻辑就行,这里给你两种实用方案:


先修正列表页的小问题(不影响核心功能,但更规范)

首先在Polis.js里,记得把Firestore文档的id加入到政客数据中(后续不管哪种方案都需要),同时修正样式写法和列表key的位置:

import React, { useEffect, useState } from 'react'
import { Button, Card, Col, Form, FormLabel, Row } from 'react-bootstrap';
import app from '../firebase'
import { BsChevronRight } from 'react-icons/bs'
import { Link } from "react-router-dom";

function Polis() {
  const [politicians, setPolis] = useState([]);
  const [loading, setLoading] = useState(false);
  const ref = app.firestore().collection("politicians");

  function getPolis() {
    setLoading(true);
    ref.onSnapshot((querySnapshot) => {
      const items = [];
      querySnapshot.forEach((doc) => {
        // 把Firestore文档ID加入数据,方便后续查询或传参
        items.push({...doc.data(), id: doc.id}); 
      });
      setPolis(items);
      setLoading(false);
    });
  }

  useEffect(() => {
    getPolis();
  }, []);

  if (loading) {
    return <h1>Loading...</h1>;
  }

  return (
    <div style={{minWidth: '100%'}}> {/* 修正之前的style语法错误 */}
      <h1>Nassau County Politicians</h1>
      <Card>
        <Card.Title>
          <Form>
            <FormLabel>Search</FormLabel>
          </Form>
        </Card.Title>
      </Card>
      <Row xs={2} md={5} lg={8}>
        {politicians.map((politician) => (
          <Col key={politician.id}> {/* key放在列表根元素上更规范 */}
            <Card style={{ width: '15rem' }}>
              <Card.Img src={politician.img} />
              <Card.Body>
                <Card.Title>{politician.name}</Card.Title>
                <Card.Text>
                  <h6>{politician.position}</h6>
                  <h6>{politician.party}</h6>
                  {/* 这里的跳转链接会根据方案不同修改 */}
                  <Link to={`/poliprofile/${politician.id}`}>
                    <Button variant='primary'>
                      <BsChevronRight />
                    </Button>
                  </Link>
                </Card.Text>
              </Card.Body>
            </Card>
          </Col>
        ))}
      </Row>
    </div>
  );
}
export default Polis;

方案一:通过路由传ID,详情页重新查询Firebase(推荐)

这种方式更适合数据可能实时更新的场景,只需要传递唯一标识,不需要传大量数据,而且能保证详情页拿到最新数据。

1. 修改列表页的跳转链接

把政客的文档ID作为路由参数传递:

<Link to={`/poliprofile/${politician.id}`}>
  <Button variant='primary'>
    <BsChevronRight />
  </Button>
</Link>

2. 改造详情页(PoliProfile.js)

用useParams获取路由里的ID,然后单独查询该政客的Firestore文档:

import React, { useEffect, useState } from "react";
import { Card, Spinner } from 'react-bootstrap';
import { useParams } from "react-router-dom";
import app from '../firebase'; // 只需要复用Firebase配置,不用导入Polis组件

function PoliProfile() {
  const { id } = useParams(); // 获取路由中的政客ID
  const [politician, setPolitician] = useState(null);
  const [loading, setLoading] = useState(true);
  // 指向单个政客的Firestore文档引用
  const docRef = app.firestore().collection("politicians").doc(id);

  useEffect(() => {
    const getPolitician = async () => {
      try {
        const doc = await docRef.get();
        if (doc.exists) {
          setPolitician(doc.data());
        } else {
          console.log("未找到该政客的数据");
        }
      } catch (error) {
        console.error("获取数据失败:", error);
      } finally {
        setLoading(false);
      }
    };

    getPolitician();
  }, [id]);

  if (loading) {
    return <Spinner animation="border" />;
  }

  if (!politician) {
    return <h2>该政客不存在</h2>;
  }

  return (
    <Card style={{ width: '15rem' }} >
      <Card.Img src={politician.img || "https://static.vecteezy.com/system/resources/previews/002/318/271/non_2x/user-profile-icon-free-vector.jpg"} />
      <Card.Body>
        <Card.Title>{politician.name}</Card.Title>
        <Card.Text>
          <h2>{politician.position}</h2>
          <h3>{politician.party}</h3>
        </Card.Text>
      </Card.Body>
    </Card>
  );
}
export default PoliProfile;

方案二:通过路由state直接传递完整数据

如果数据不会频繁更新,也可以直接把政客的完整数据通过路由的state传递,详情页不需要再次请求Firebase。

1. 修改列表页的跳转链接

<Link to={{
  pathname: "/poliprofile",
  state: { politician: politician } // 传递完整的政客数据
}}>
  <Button variant='primary'>
    <BsChevronRight />
  </Button>
</Link>

2. 改造详情页(PoliProfile.js)

用useLocation获取路由state里的数据:

import React from "react";
import { Card } from 'react-bootstrap';
import { useLocation } from "react-router-dom";

function PoliProfile() {
  const location = useLocation();
  const politician = location.state?.politician; // 获取传递的政客数据

  if (!politician) {
    return <h2>无法获取政客数据</h2>;
  }

  return (
    <Card style={{ width: '15rem' }} >
      <Card.Img src={politician.img || "https://static.vecteezy.com/system/resources/previews/002/318/271/non_2x/user-profile-icon-free-vector.jpg"} />
      <Card.Body>
        <Card.Title>{politician.name}</Card.Title>
        <Card.Text>
          <h2>{politician.position}</h2>
          <h3>{politician.party}</h3>
        </Card.Text>
      </Card.Body>
    </Card>
  );
}
export default PoliProfile;

关于Firebase代码复用的小建议

  • 不需要导入整个Polis组件,只需要复用Firebase的初始化配置(app)即可。
  • 如果多个组件都需要查询Firestore,可以把查询逻辑封装成自定义Hook(比如useFirestoreDocument),减少重复代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 00:17:47