React页面间传递ID:如何获取/watch/:id中的ID并播放对应视频
如何在React的/watch页面获取URL中的视频ID并播放对应视频
嘿,看起来你已经搞定了路由跳转的部分,接下来只需要通过React Router拿到URL里的ID,再匹配对应的视频数据就能播放啦,下面是具体的实现步骤:
1. 先把路由配置改成支持参数的形式
首先得在你的路由配置文件(比如App.js或者单独的路由文件)里,给/watch页面定义带参数的路由,这样React Router才能识别URL里的ID:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import WatchPage from './components/WatchPage'; // 记得创建这个Watch页面组件 import VideoContainer from './components/VideoContainer'; function App() { return ( <Router> <Routes> <Route path="/" element={<VideoContainer />} /> {/* 这里的`:id`就是我们要抓取的动态参数 */} <Route path="/watch/:id" element={<WatchPage />} /> </Routes> </Router> ); } export default App;
2. 创建WatchPage组件,获取URL参数并匹配视频
接下来在WatchPage组件里,用react-router-dom提供的useParams钩子来拿到URL里的ID,然后从视频数据里找到对应的条目:
import React, { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { postVideos } from '../services/MyCuruApi'; export default function WatchPage() { // 从URL里拿到id,注意这里返回的是字符串类型哦 const { id } = useParams(); const [currentVideo, setCurrentVideo] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { // 调用你现有的接口获取所有视频数据 postVideos().then(data => { // 找到对应id的视频,记得把字符串id转成数字再匹配 const targetVideo = data.find(video => video.id === parseInt(id)); setCurrentVideo(targetVideo); setLoading(false); }); }, [id]); // 当id变化时重新请求匹配 // 加载状态提示 if (loading) { return <div>视频加载中...</div>; } // 如果没找到对应视频的提示 if (!currentVideo) { return <div>抱歉,没找到这个视频哦</div>; } // 渲染视频播放页面 return ( <div className="watch-page"> <h2>{currentVideo.title}</h2> <p>上传者:{currentVideo.username}</p> {/* 用原生video标签播放视频 */} <video controls style={{ width: '80%', maxWidth: '1000px' }}> <source src={currentVideo.video_path} type="video/mp4" /> 你的浏览器不支持HTML5视频播放,请更换浏览器尝试 </video> <div className="video-description"> <h4>视频描述</h4> <p>{currentVideo.description}</p> </div> </div> ); }
3. 可选优化:避免重复请求视频数据
现在每次进入WatchPage都会重新调用postVideos()接口,有点浪费资源。如果你的视频数据在多个组件都要用,推荐用React Context或者状态管理工具把数据全局存起来,比如这样:
第一步:创建VideoContext
import { createContext, useContext, useState, useEffect } from 'react'; import { postVideos } from '../services/MyCuruApi'; // 创建上下文 const VideoContext = createContext(); // 上下文提供者组件 export function VideoProvider({ children }) { const [videos, setVideos] = useState([]); const [loading, setLoading] = useState(true); // 只在初始化时请求一次数据 useEffect(() => { postVideos().then(data => { setVideos(data); setLoading(false); }); }, []); return ( <VideoContext.Provider value={{ videos, loading }}> {children} </VideoContext.Provider> ); } // 自定义钩子,方便组件使用上下文 export function useVideos() { return useContext(VideoContext); }
第二步:在App.js里包裹Provider
import { VideoProvider } from './contexts/VideoContext'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import WatchPage from './components/WatchPage'; import VideoContainer from './components/VideoContainer'; function App() { return ( <VideoProvider> <Router> <Routes> <Route path="/" element={<VideoContainer />} /> <Route path="/watch/:id" element={<WatchPage />} /> </Routes> </Router> </VideoProvider> ); } export default App;
第三步:在WatchPage里直接用上下文数据
import React from 'react'; import { useParams } from 'react-router-dom'; import { useVideos } from '../contexts/VideoContext'; export default function WatchPage() { const { id } = useParams(); const { videos, loading } = useVideos(); // 直接从上下文的videos数组里找对应视频 const currentVideo = videos.find(video => video.id === parseInt(id)); if (loading) { return <div>视频加载中...</div>; } if (!currentVideo) { return <div>抱歉,没找到这个视频哦</div>; } // 下面的渲染逻辑和之前一样 return ( <div className="watch-page"> {/* ...省略其他内容 */} </div> ); }
这样就不用每次进入WatchPage都请求接口了,性能会更好~
内容的提问来源于stack exchange,提问作者Jem
相关产品推荐
相关产品推荐

