You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:24:03