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

react-router-dom中useLocation()报错及BrowserRouter使用问题求助

问题分析与解决方法

核心问题

你在App组件中直接调用了useLocation()和useNavigate(),但App组件本身并不在<BrowserRouter>的上下文范围内——你的<BrowserRouter>是在App的return语句里渲染的,这意味着当App组件执行钩子调用时,Router上下文还未创建,所以触发了错误。

另外,你使用的<Switch>是react-router-dom v5的语法,在v6版本中已经被<Routes>取代,继续使用会导致新的错误。


解决步骤

方案1:将BrowserRouter移到App组件外部(推荐)

修改index.js,用<BrowserRouter>包裹整个App组件,这样整个应用都处于Router上下文之中:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

然后修改App.js,移除内部的<BrowserRouter>,同时替换<Switch>为v6的<Routes>,并调整Route的写法:

import { useState } from "react";
import {
  Routes,
  Route,
  useLocation,
  useNavigate,
} from "react-router-dom";
import "./App.css";
import Header from "./Header";
import LandingPage from "./LandingPage";
import NavigationMenu from "./Navigation";
import Product from "./Product";

const products = [
  {
    name: "Product 1",
    price: "£19.99",
    image: "https://osofimages.s3.us-east-2.amazonaws.com/ZOOM/2018117_HR.jpg",
  },
  {
    name: "Product 2",
    price: "£29.99",
    image: "https://osofimages.s3.us-east-2.amazonaws.com/ZOOM/2815694_HR.jpg",
  },
  {
    name: "Product 3",
    price: "£39.99",
    image:
      "https://www.hardwarestore.com/media/catalog/product/1/2/126043_1.jpg?quality=80&bg-color=255,255,255&fit=bounds&height=&width=",
  },
];

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const location = useLocation();
  const navigate = useNavigate();

  function handleLogout() {
    setIsLoggedIn(false);
    alert("User has logged out");
    navigate("/");
  }

  return (
    <div className="App">
      <Header isLoggedIn={isLoggedIn} onLogout={handleLogout} />
      <NavigationMenu />
      <Routes>
        <Route path="/" element={<LandingPage />} />
        <Route path="/shop" element={
          <div className="products-container">
            {products.map((product, index) => (
              <Product
                key={index}
                name={product.name}
                price={product.price}
                image={product.image}
              />
            ))}
          </div>
        } />
      </Routes>
    </div>
  );
}
export default App;

方案2:将钩子逻辑移到Router内部组件

如果不想修改index.js,可以把使用useLocation和useNavigate的部分拆分到一个子组件中,确保该组件在<BrowserRouter>内部:

比如创建一个AuthHandler组件:

import { useNavigate } from "react-router-dom";
import { useState } from "react";

export function AuthHandler({ children }) {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const navigate = useNavigate();

  function handleLogout() {
    setIsLoggedIn(false);
    alert("User has logged out");
    navigate("/");
  }

  return children({ isLoggedIn, handleLogout });
}

然后在App.js中使用:

import { useState } from "react";
import {
  BrowserRouter,
  Routes,
  Route,
  useLocation,
} from "react-router-dom";
import "./App.css";
import Header from "./Header";
import LandingPage from "./LandingPage";
import NavigationMenu from "./Navigation";
import Product from "./Product";
import { AuthHandler } from "./AuthHandler";

// ... products数组保持不变

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <AuthHandler>
          {({ isLoggedIn, handleLogout }) => (
            <>
              <Header isLoggedIn={isLoggedIn} onLogout={handleLogout} />
              <NavigationMenu />
              <Routes>
                <Route path="/" element={<LandingPage />} />
                <Route path="/shop" element={
                  <div className="products-container">
                    {products.map((product, index) => (
                      <Product
                        key={index}
                        name={product.name}
                        price={product.price}
                        image={product.image}
                      />
                    ))}
                  </div>
                } />
              </Routes>
            </>
          )}
        </AuthHandler>
      </BrowserRouter>
    </div>
  );
}
export default App;

关键注意点

  • 所有使用useLocation、useNavigate、useParams等Router钩子的组件,必须处于<BrowserRouter>(或其他Router组件,如HashRouter)的上下文范围内。
  • react-router-dom v6中,<Switch>已被<Routes>替代,Route的子元素需要通过element属性传递,不再支持直接嵌套组件。

内容的提问来源于stack exchange,提问作者saf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:19:32