React如何强制跳转路由?useHistory返回undefined报错如何解决
问题原因说明
这个报错和App是函数组件无关,是两个核心使用错误导致:
- 错误1:你使用的
react-router-dom@8.1.2属于v6及以上版本,该版本已经完全移除了useHistoryAPI,替代方案为useNavigate - 错误2:所有react-router的路由相关Hook(包括
useHistory/useNavigate)必须在<BrowserRouter>包裹的子组件内部调用,你当前的代码中,useHistory是在App组件顶层调用,而App组件的返回值才包裹了<BrowserRouter>,相当于App本身不在路由上下文范围内,必然无法获取到路由实例。
解决步骤
步骤1:将BrowserRouter移到App组件外层
修改你的项目入口文件(通常是src/index.js),把<BrowserRouter>套在App组件外面,示例:
import { BrowserRouter } from 'react-router-dom' import App from './App' // 渲染部分改成 ReactDOM.createRoot(document.getElementById('root')).render( <BrowserRouter> <App /> </BrowserRouter> )
然后删除App.js里的<BrowserRouter>标签,避免重复嵌套。
步骤2:替换useHistory为useNavigate
修改App.js里的路由API调用:
首先把导入语句从
import { BrowserRouter, Route, Switch, useHistory } from "react-router-dom";
改成
import { Route, Routes, useNavigate } from "react-router-dom";
注意:v6版本同时移除了Switch组件,替换为Routes组件
然后把App组件内的const history = useHistory();替换为:
const navigate = useNavigate();
再修改onRequestClose函数里的跳转逻辑:
let onRequestClose = () => { setIsOpen(false); setCart(GetCart); navigate('/') // 替换原来的history.push('/') }
步骤3:适配v6的Route写法
v6的Route组件不再支持嵌套子元素的写法,需要通过element属性传入组件,你原来的Switch包裹的路由部分需要调整为:
<Routes> <Route path="/cart" element={ <Suspense fallback={<div>Loading...</div>}> <div> <table className="table table-striped table-bordered"> <thead> <tr> <th className="number">Item Number</th> <th className="price">Price</th> <th className="quantity">Quantity</th> </tr> </thead> <tbody> {cart.map(item => <tr key={item.ItemNumber}> <td>{item.ItemNumber}</td> <td>{formatter.format(item.Price)}</td> <td>{item.Quantity}</td> <td><Button className="BtnIncrement" onClick={() => handleIncrementClick(item)}>{'+'}</Button></td> <td><Button className="BtnDecrement" onClick={() => handleDecrementClick(item)}>{'-'}</Button></td> </tr> )} </tbody> </table> <Button onClick={() => handleClick()}>Checkout</Button> {isOpen ? <CheckoutModal onRequestClose={onRequestClose} /> : null} </div> </Suspense> } /> <Route path="/portal" element={ <Suspense fallback={<div>Loading...</div>}> <Portal /> </Suspense> } /> <Route path="/" element={ <> <Slideshow id="slideshow" /> <div id="productContainer"> <br /> <h3>Featured Products</h3> <br /> <Suspense fallback={<div>Loading...</div>}> <FeaturedCards setCartFunc={setCart} /> </Suspense> <br /> <h3>Most Popular</h3> <br /> <Suspense fallback={<div>Loading...</div>}> <ProdCard /> </Suspense> <br /> <h3>New Products</h3> <br /> <Suspense fallback={<div>Loading...</div>}> <ProdCard /> </Suspense> </div> </> } /> </Routes>
修改完成后即可正常实现关闭Modal后跳转首页的逻辑。
内容的提问来源于stack exchange,提问作者Randy
相关产品推荐
相关产品推荐

