react-router-dom v6中使用useLocation()无法获取对象的问题
问题分析与解决
问题根源
你遇到的Cannot read properties of null (reading 'movie')错误,核心原因有两个:
- 直接访问/watch路由:如果不是通过ListItem组件的Link跳转,而是直接在地址栏输入
/watch,此时location.state会是null,自然无法读取movie属性。 - ListItem组件初始状态问题:组件挂载后
useEffect异步执行,电影数据请求完成前,movie是空对象,此时点击Link传递的state虽非null,但后续movie.video也会出现undefined的问题。
修复方案
1. 给Watch组件添加空值防护
修改Watch组件,先判断location.state是否存在,再读取movie,同时处理video地址的空值情况:
import './watch.scss' import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import { Link, useLocation, Navigate } from 'react-router-dom'; export default function Watch() { const location = useLocation(); // 若state不存在,直接跳回首页 if (!location.state) { return <Navigate to="/" />; } const movie = location.state.movie; return ( <div className="watch"> <Link to="/"> <div className="back"> <ArrowBackIcon /> Home </div> </Link> {/* 给video的src加可选链和默认值,避免报错 */} <video className="video" autoPlay controls src={movie?.video || ''} /> </div> ); }
2. 优化ListItem组件的Link渲染逻辑
确保电影数据加载完成后再渲染可点击的Link,避免传递不完整的movie数据:
const [isHovered, setIsHovered] = useState(false); const [movie, setMovie] = useState(null); // 初始设为null,明确未加载状态 useEffect(() => { const getMovie = async () => { try { const res = await axios.get("/movies/find/" + item, { headers: { token: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzYTQxNzViOTM1ZWYxODY1YmRjMDRmNCIsImlzQWRtaW4iOnRydWUsImlhdCI6MTY3MjIzODY2NywiZXhwIjoxNjcyNjcwNjY3fQ.R99XRjYNMSy0jF7glDx9WVsDLYoVAeOcjTB8kEdf4yQ", } }) setMovie(res.data) } catch (err) { console.log(err); } } getMovie(); }, [item]) // 未加载完成时显示加载状态 if (!movie) { return <div>Loading...</div>; } return ( <Link to={{ pathname: '/watch', state: { movie } }}> {/* 你的ListItem内容 */} </Link> )
额外注意事项
- React Router v6中
Link的to对象写法是兼容的,但要确保传递的state数据是可序列化的(不要传函数等非序列化值)。 - 生产环境不要把token硬编码在代码里,应放在环境变量中避免泄露。
内容的提问来源于stack exchange,提问作者Harshil Gajjar
相关产品推荐
相关产品推荐

