React跨组件传递赛事数据:跳转详情页实现方案求助
React 体育赛事应用:实现选中赛事的跨页面数据传递
针对你遇到的跨组件数据传递问题,这里提供三种适合新手的解决方案,按需选择即可:
方案一:通过 React Router 的路由 State 传递数据
这是最直接的方式,适合不需要刷新页面保留数据的场景:
首页组件(Home.jsx)
import { useNavigate } from 'react-router-dom'; import popularData from './popular.json'; function Home() { const navigate = useNavigate(); const handleMatchClick = (match) => { // 跳转时将赛事数据存入路由 state navigate('/game', { state: { selectedMatch: match } }); }; return ( <div> <h2>热门赛事</h2> <ul> {popularData.map(match => ( <li key={match.id} onClick={() => handleMatchClick(match)}> {match.homeTeam} vs {match.awayTeam} </li> ))} </ul> </div> ); } export default Home;
赛事详情页组件(Game.jsx)
import { useLocation } from 'react-router-dom'; function Game() { const location = useLocation(); // 从路由 state 中取出数据,加默认值避免空值报错 const selectedMatch = location.state?.selectedMatch || {}; if (!Object.keys(selectedMatch).length) { return <div>未选中任何赛事</div>; } return ( <div className="game-detail"> <h1>{selectedMatch.homeTeam} vs {selectedMatch.awayTeam}</h1> <p>日期:{selectedMatch.date}</p> <p>场馆:{selectedMatch.venue}</p> {/* 渲染其他赛事信息 */} </div> ); } export default Game;
注意:刷新页面后路由 state 会丢失,若需要刷新后仍保留数据,优先选方案二。
方案二:通过 URL 参数传递赛事 ID,重新获取数据
适合需要刷新页面、分享页面的场景:
首页组件(Home.jsx)
import { useNavigate } from 'react-router-dom'; import popularData from './popular.json'; function Home() { const navigate = useNavigate(); const handleMatchClick = (matchId) => { // 将赛事 ID 作为 URL 参数传递 navigate(`/game/${matchId}`); }; return ( <div> <h2>热门赛事</h2> <ul> {popularData.map(match => ( <li key={match.id} onClick={() => handleMatchClick(match.id)}> {match.homeTeam} vs {match.awayTeam} </li> ))} </ul> </div> ); } export default Home;
路由配置(App.jsx)
import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Home from './Home'; import Game from './Game'; function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> {/* 配置带 ID 参数的路由规则 */} <Route path="/game/:matchId" element={<Game />} /> </Routes> </BrowserRouter> ); } export default App;
赛事详情页组件(Game.jsx)
import { useParams } from 'react-router-dom'; import popularData from './popular.json'; function Game() { const { matchId } = useParams(); // 根据 ID 从 JSON 中匹配对应赛事(注意转换类型,避免字符串/数字不匹配) const selectedMatch = popularData.find(match => match.id.toString() === matchId); if (!selectedMatch) { return <div>未找到该赛事</div>; } return ( <div className="game-detail"> <h1>{selectedMatch.homeTeam} vs {selectedMatch.awayTeam}</h1> <p>日期:{selectedMatch.date}</p> <p>场馆:{selectedMatch.venue}</p> {/* 渲染其他赛事信息 */} </div> ); } export default Game;
方案三:使用 React Context 做全局状态管理
适合应用规模较大、多个组件需要共享赛事数据的场景:
创建全局上下文(MatchContext.jsx)
import { createContext, useState, useContext } from 'react'; const MatchContext = createContext(); export function MatchProvider({ children }) { const [selectedMatch, setSelectedMatch] = useState(null); return ( <MatchContext.Provider value={{ selectedMatch, setSelectedMatch }}> {children} </MatchContext.Provider> ); } export function useMatch() { return useContext(MatchContext); }
包裹全局上下文(App.jsx)
import { BrowserRouter, Routes, Route } from 'react-router-dom'; import { MatchProvider } from './MatchContext'; import Home from './Home'; import Game from './Game'; function App() { return ( <MatchProvider> <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="/game" element={<Game />} /> </Routes> </BrowserRouter> </MatchProvider> ); } export default App;
首页组件(Home.jsx)
import { useNavigate } from 'react-router-dom'; import { useMatch } from './MatchContext'; import popularData from './popular.json'; function Home() { const navigate = useNavigate(); const { setSelectedMatch } = useMatch(); const handleMatchClick = (match) => { setSelectedMatch(match); navigate('/game'); }; return ( <div> <h2>热门赛事</h2> <ul> {popularData.map(match => ( <li key={match.id} onClick={() => handleMatchClick(match)}> {match.homeTeam} vs {match.awayTeam} </li> ))} </ul> </div> ); } export default Home;
赛事详情页组件(Game.jsx)
import { useMatch } from './MatchContext'; function Game() { const { selectedMatch } = useMatch(); if (!selectedMatch) { return <div>未选中任何赛事</div>; } return ( <div className="game-detail"> <h1>{selectedMatch.homeTeam} vs {selectedMatch.awayTeam}</h1> <p>日期:{selectedMatch.date}</p> <p>场馆:{selectedMatch.venue}</p> {/* 渲染其他赛事信息 */} </div> ); } export default Game;
内容的提问来源于stack exchange,提问作者Milo Welch
相关产品推荐
相关产品推荐

