React Router动态路由URL新标签页打开报错该如何解决?
问题根因
你对报错原因的判断是正确的,React Router 中的 location.state 存储在当前浏览器会话的历史栈中,仅通过同站点内的 Link 组件跳转时才会携带该数据。直接刷新页面、新开标签页访问URL、手动输入URL的场景下,历史栈中没有对应状态数据,就会出现取值报错。这不是动态路由的固有缺陷,是数据传递方式选择不当导致的问题。
解决方案
1. 统一路由参数规则
你当前路由定义的路径为 /movie/:id,但跳转时实际拼接的是电影标题,首先修正跳转逻辑,用全局唯一的电影ID作为路由参数,避免标题重复、特殊字符转义的问题:
// Result组件内Link部分修正后的代码 <Link to={{ pathname: `/movie/${props.id}`, state: { ...props }, }} >
2. 改造ResultPage的取值逻辑,添加数据兜底
不再完全依赖location.state取数,做两层兼容:
- 从同页面跳转过来有
location.state时,直接用该数据渲染,无需额外发请求,保证跳转体验 - 无
location.state时,从URL路由参数中取出电影ID,调用单电影详情接口拉取数据后再渲染
以下是React Router v5版本的ResultPage示例代码:
import { useEffect, useState } from 'react'; export default function ResultPage(props) { const [movieData, setMovieData] = useState(props.location.state); const [loading, setLoading] = useState(!props.location.state); // 从路由参数中拿到电影ID const movieId = props.match.params.id; useEffect(() => { // 没有state数据时调用接口拉取电影详情 if (!props.location.state) { // 此处替换为你实际使用的单电影查询接口 fetch(`https://api.themoviedb.org/3/movie/${movieId}?api_key=你的API_KEY`) .then(res => res.json()) .then(data => { setMovieData(data); setLoading(false); }) .catch(err => { // 可添加异常处理,比如跳转到404页、提示电影不存在 setLoading(false); }) } }, [movieId, props.location.state]) if (loading) return <div>加载中...</div> if (!movieData) return <div>未查询到对应电影信息</div> // 此处为你原来的页面渲染逻辑,直接使用movieData即可 return ( <div> <h1>{movieData.title}</h1> {/* 剩余渲染内容 */} </div> ) }
可选优化
如果想要进一步提升体验,可以在搜索结果页缓存已经拉取过的电影数据,新开页面访问时优先从缓存取数,减少重复接口请求。
内容的提问来源于stack exchange,提问作者cdt
相关产品推荐
相关产品推荐

