React路由条件跳转问题:无效Product ID跳转失败并报错
React路由重定向问题排查与解决
我的路由配置
<Routes> <Route exact path="/" element={<Home />} /> <Route exact path='/login' element={<Login />} /> <Route exact path='/about' element={<About />} /> <Route exact path='/store' element={<Store />} /> <Route exact path='/store/:productID' element={<Product />} /> <Route path={['/not-found', '*']} element={<NotFound />} /> </Routes>
需求与尝试过程
我需要在Product页面展示存在的商品信息,若商品ID不存在则自动重定向到not-found页面。
第一次尝试:调用navigate函数
我编写了以下代码:
{!check && navigate("/not-found", {replace: true})} <div className="container"> <ul> <li>Product ID: {productID}</li> <li>Name: {check.name}</li> <li>Price: {check.price}</li> <li><img src={check.image} /></li> </ul> </div>
但页面抛出错误:
Uncaught TypeError: meta.relativePath.startsWith is not a function
第二次尝试:使用<Navigate>组件
改用组件方式实现重定向:
{!check && <Navigate to="/not-found" />}
结果不存在的ID对应的页面仍然显示空白。
问题原因与解决方法
1. navigate函数报错的原因
navigate属于导航副作用函数,只能在事件处理函数或useEffect这类副作用钩子中调用,直接放在JSX渲染逻辑里会触发React渲染流程冲突,导致报错。
2. <Navigate>组件无效的原因
当check为假时,虽然渲染了<Navigate>,但组件后续仍会尝试渲染依赖check的内容(如check.name),这会引发未定义属性读取错误,中断渲染流程,导致重定向逻辑无法正常执行。
正确实现方式
方式一:前置条件判断,提前返回重定向
在组件开头先做判断,若商品不存在直接返回重定向组件,避免后续错误渲染:
if (!check) { return <Navigate to="/not-found" replace />; } return ( <div className="container"> <ul> <li>Product ID: {productID}</li> <li>Name: {check.name}</li> <li>Price: {check.price}</li> <li><img src={check.image} /></li> </ul> </div> );
方式二:用useEffect处理导航逻辑
如果是异步获取商品数据后判断,可以把导航逻辑放在useEffect中:
import { useEffect } from 'react'; // ... useEffect(() => { if (!check) { navigate("/not-found", { replace: true }); } }, [check, navigate]); return ( <div className="container"> {check ? ( <ul> <li>Product ID: {productID}</li> <li>Name: {check.name}</li> <li>Price: {check.price}</li> <li><img src={check.image} /></li> </ul> ) : null} </div> );
补充:路由配置优化
React Router v6中已经移除了exact属性,Routes组件会自动匹配最精确的路径,可简化路由配置:
<Routes> <Route path="/" element={<Home />} /> <Route path='/login' element={<Login />} /> <Route path='/about' element={<About />} /> <Route path='/store' element={<Store />} /> <Route path='/store/:productID' element={<Product />} /> <Route path='/not-found' element={<NotFound />} /> <Route path='*' element={<Navigate to="/not-found" replace />} /> </Routes>
这样所有未匹配的路径都会直接重定向到not-found页面,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Jupixel
相关产品推荐
相关产品推荐

