React路由问题:点击Bootstrap卡片图片跳转至帖子详情页
解决Bootstrap卡片点击跳转详情页并获取帖子ID的问题
1. 先配置路由
首先确保你装了react-router-dom,没装的话执行:
npm install react-router-dom
然后在路由配置文件(比如App.js)里添加详情页的路由规则,带上:id参数:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { Activities } from './path/to/activities'; import Detail from './path/to/detail'; function App() { return ( <Router> <Routes> <Route path="/" element={<Activities />} /> {/* 配置带id参数的详情页路由 */} <Route path="/activity/:id" element={<Detail />} /> </Routes> </Router> ); } export default App;
2. 给卡片图片加跳转逻辑
修改activities.js,引入Link组件,把图片包裹进去,跳转路径带上当前帖子的唯一ID(如果你的帖子用name当唯一标识,就替换成activity.name):
import React from 'react' import Card from 'react-bootstrap/Card'; import { Link } from 'react-router-dom'; // 新增引入 import "bootstrap/dist/css/bootstrap.min.css"; export const Activities = ({ activityListings, loading }) => { if (loading) { return <h1>Loading...</h1>; } return ( <div className="activities-container"> {activityListings.map(activity => { let description = activity.blurbs[1].value; if (description.split(' ')[0] === "-") { description = description.replace('-', ''); } return ( <Card key={activity.id}> {/* 把key换成唯一id,避免重复渲染问题 */} <Card.Body> {/* 用Link包裹图片,点击跳转到对应详情页 */} <Link to={`/activity/${activity.id}`}> <Card.Img variant="top" src={activity.images[0]} style={{cursor: 'pointer'}} /> </Link> <Card.Title>{activity.name}</Card.Title> <Card.Subtitle className="mb-2 text-muted"> {description.split(' ').slice(0, 10).join(' ') + " ..."} </Card.Subtitle> <span className="rating"> <i className="fa fa-star"></i> {Math.round(activity.reviewMeta?.avgRating * 100) / 100} </span> <br /> <Card.Text className="card-location"> {activity.primaryRegion?.name} </Card.Text> </Card.Body> </Card> ) })} </div> ) }
如果需要先执行某些逻辑再跳转(比如埋点统计),可以用useNavigate替代Link:
import { useNavigate } from 'react-router-dom'; // 组件内部初始化 const navigate = useNavigate(); // 给图片加点击事件 <Card.Img variant="top" src={activity.images[0]} style={{cursor: 'pointer'}} onClick={() => { // 这里加前置逻辑,比如console.log('点击了帖子:', activity.id) navigate(`/activity/${activity.id}`); }} />
3. 在Detail组件中获取ID并展示详情
用useParams钩子拿到路由里的id,然后根据ID找到对应帖子数据(可以通过props传整个列表,或者发起API请求获取单条数据):
import React from 'react'; import { useParams } from 'react-router-dom'; const Detail = ({ activityListings }) => { const { id } = useParams(); // 根据id筛选出对应帖子 const activity = activityListings.find(item => item.id === id); if (!activity) { return <h1>帖子不存在</h1>; } return ( <div className="detail-container"> <h1>{activity.name}</h1> <img src={activity.images[0]} alt={activity.name} style={{width: '100%'}} /> <p>{activity.blurbs[1].value}</p> <p>评分:{Math.round(activity.reviewMeta?.avgRating * 100) / 100}</p> <p>地区:{activity.primaryRegion?.name}</p> {/* 这里添加更多详情内容 */} </div> ); }; export default Detail;
如果是通过API获取单条数据,用useEffect发起请求:
import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; const Detail = () => { const { id } = useParams(); const [activity, setActivity] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { // 替换成你的实际API地址 fetch(`/api/activities/${id}`) .then(res => res.json()) .then(data => { setActivity(data); setLoading(false); }) .catch(err => { console.error('获取详情失败:', err); setLoading(false); }); }, [id]); if (loading) { return <h1>Loading...</h1>; } if (!activity) { return <h1>帖子不存在</h1>; } return ( <div className="detail-container"> <h1>{activity.name}</h1> <img src={activity.images[0]} alt={activity.name} style={{width: '100%'}} /> <p>{activity.blurbs[1].value}</p> <p>评分:{Math.round(activity.reviewMeta?.avgRating * 100) / 100}</p> <p>地区:{activity.primaryRegion?.name}</p> </div> ); }; export default Detail;
注意事项
- 路由参数名要和
useParams里取的一致,比如路由是:id,就用const { id } = useParams();如果用name当标识,路由改成/activity/:name,然后取const { name } = useParams()。 - 卡片的
key一定要用唯一值(比如id),不要用name,避免重复数据导致React渲染异常。
内容的提问来源于stack exchange,提问作者Charlotte M
相关产品推荐
相关产品推荐

