点击卡片跳转页展示详情 Firebase v8升v9模块化传id问题
问题核心原因
你的代码存在两类问题导致无法正常拉取数据:
- 路由跳转链路没有正确传递文档id,详情页拿到的id值不合法,无法匹配到Firestore里的对应文档
- Firebase v9模块化API调用逻辑错误,混淆了Promise对象和回调返回的文档快照,调用了不存在的方法导致数据读取失败
修复步骤
1. 列表页卡片跳转时正确携带id
点击卡片触发路由跳转时,必须把当前卡片对应的电影文档id拼入路由参数,以React Router v6为例:
import { useNavigate } from 'react-router-dom'; // 电影列表卡片组件 const MovieCard = ({ movie }) => { const navigate = useNavigate(); const onCardClick = () => { // 跳转到详情页路由,路由需提前定义为 /movie/detail/:id 格式 navigate(`/movie/detail/${movie.id}`); }; return ( <div onClick={onCardClick} className="movie-card"> {/* 卡片原有展示内容 */} </div> ); };
2. 详情页从路由中提取正确的id
详情页加载时首先从路由参数中解析传递过来的文档id:
import { useParams } from 'react-router-dom'; const MovieDetailPage = () => { // 提取路由参数中的id,字段名需要和路由定义的参数名保持一致 const { id } = useParams(); const [detailData, setDetailData] = useState(null); const [loading, setLoading] = useState(false); // 后续数据请求逻辑 }
3. 修正Firebase v9的数据查询逻辑
原有代码错误地在Promise对象上调用快照方法,需要修正为操作回调返回的文档快照对象,同时增加id合法性校验:
useEffect(() => { // id不存在时终止请求,避免无效查询 if (!id) { setLoading(false); return; } setLoading(true); // 构造文档引用 const movieDocRef = doc(db, 'movie', id); getDoc(movieDocRef) .then((docSnapshot) => { // exists()、data() 都是回调返回的docSnapshot实例上的方法 if (docSnapshot.exists()) { // 读取文档数据使用data()方法,同时把文档id合并入数据方便后续使用 setDetailData({ id: docSnapshot.id, ...docSnapshot.data() }); } else { console.log('未找到对应电影文档'); } }) .catch(err => { console.error('拉取电影详情失败:', err); }) .finally(() => { setLoading(false); }); }, [id]);
校验注意事项
- 先在详情页组件顶层打印
id值,确认拿到的id和Firestore控制台中movie集合下的目标文档id完全一致,无undefined、多余空格、拼写错误问题 - 确认已经正确导入Firebase相关依赖:
import { doc, getDoc } from "firebase/firestore"; import { db } from '@/utils/firebase'; // 替换为你项目中db实例的实际导入路径 - 页面渲染时增加加载态和空态判断,避免数据未返回时触发渲染报错:
if (loading) return <div>内容加载中...</div>; if (!detailData) return <div>暂无对应电影信息</div>; return ( <div className="movie-detail"> {/* 详情字段正常渲染逻辑 */} </div> );
内容的提问来源于stack exchange,提问作者Da Cratos
相关产品推荐
相关产品推荐

