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

React Router Dom:如何根据当前路径控制组件的显示与隐藏?

解决方案

要实现根据路径显示/隐藏Navbar、Newsletter、Footer这类全局组件,核心是让组件能访问到路由上下文(useLocation必须在BrowserRouter内部使用),以下是两种可行方案:

方案一:拆分内部组件(快速改造)

把原App中BrowserRouter内部的内容拆成独立组件,该组件处于路由上下文内,可正常使用useLocation:

import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom';

// 外层App仅负责包裹BrowserRouter
function App() {
  return (
    <BrowserRouter>
      <AppContent />
    </BrowserRouter>
  );
}

// 内部组件,可访问路由上下文
function AppContent() {
  const location = useLocation();
  // 定义需要隐藏全局组件的路径
  const hiddenPaths = ['/login', '/register', '/account', '/forgot-password'];
  
  // 按需判断是否显示对应组件
  const showNavbar = !hiddenPaths.includes(location.pathname);
  const showNewsletter = !hiddenPaths.includes(location.pathname);
  const showFooter = !hiddenPaths.includes(location.pathname); // 可按需调整

  return (
    <>
      <Wrapper>
        {showNavbar && (
          <>
            <Announcement />
            <Navbar />
          </>
        )}
        <Routes>
          <Route index path="/" element={<Home />}></Route>
          <Route path="/products" element={<ProductList />}></Route>
          <Route path="/products/:category" element={<ProductList category="true" />}></Route>
          <Route path="/product/:id" element={<Product />}></Route>
          <Route path="/register" element={isAuthenticated ? <Navigate replace to="/" /> : <Register />}></Route>
          <Route path="/login" element={isAuthenticated ? <Navigate replace to="/" /> : <Login />}></Route>
          <Route path="/account" element={isAuthenticated ? <Navigate replace to="/" /> : <Account />}></Route>
          <Route path="/forgot-password" element={isAuthenticated ? <Navigate replace to="/" /> : <ForgotPassword />}></Route>
          <Route path="/cart" element={<Cart />}></Route>
          <Route path="/wishlist" element={<Wishlist />}></Route>
          <Route path="/orders/tracking" element={<Tracking />}></Route>
          <Route path="/orders/checkout" element={<Checkout />}></Route>
        </Routes>
        {showNewsletter && <Newsletter />}
      </Wrapper>
      {showFooter && <Footer />}
    </>
  );
}

export default App;

方案二:使用Layout布局组件(推荐,符合React Router最佳实践)

通过Outlet创建共享布局,将全局组件封装到Layout中,路由结构更清晰,适合多布局场景:

  1. 先创建Layout组件:
import { useLocation, Outlet } from 'react-router-dom';

const Layout = () => {
  const location = useLocation();
  const hiddenPaths = ['/login', '/register', '/account', '/forgot-password'];
  
  const showNavbar = !hiddenPaths.includes(location.pathname);
  const showNewsletter = !hiddenPaths.includes(location.pathname);

  return (
    <Wrapper>
      {showNavbar && (
        <>
          <Announcement />
          <Navbar />
        </>
      )}
      <Outlet /> {/* 渲染当前路由对应的页面内容 */}
      {showNewsletter && <Newsletter />}
    </Wrapper>
  );
};
  1. 修改App.js的路由结构:
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        {/* 所有需要共享Layout的路由作为子路由 */}
        <Route element={<Layout />}>
          <Route index path="/" element={<Home />}></Route>
          <Route path="/products" element={<ProductList />}></Route>
          <Route path="/products/:category" element={<ProductList category="true" />}></Route>
          <Route path="/product/:id" element={<Product />}></Route>
          <Route path="/cart" element={<Cart />}></Route>
          <Route path="/wishlist" element={<Wishlist />}></Route>
          <Route path="/orders/tracking" element={<Tracking />}></Route>
          <Route path="/orders/checkout" element={<Checkout />}></Route>
        </Route>
        {/* 不需要Layout的路由单独定义(如登录、注册) */}
        <Route path="/register" element={isAuthenticated ? <Navigate replace="/" /> : <Register />}></Route>
        <Route path="/login" element={isAuthenticated ? <Navigate replace="/" /> : <Login />}></Route>
        <Route path="/account" element={isAuthenticated ? <Navigate replace="/" /> : <Account />}></Route>
        <Route path="/forgot-password" element={isAuthenticated ? <Navigate replace="/" /> : <ForgotPassword />}></Route>
      </Routes>
      {/* Footer如果需要判断路径,也可以放到Layout中,或者单独处理 */}
      {/* <Footer /> */}
    </BrowserRouter>
  );
}

export default App;

关键说明

  • 之前无法使用useLocation是因为该钩子必须在BrowserRouter内部的组件中调用,原App组件是渲染BrowserRouter的外层组件,不在路由上下文范围内。
  • 两种方案都能解决问题,方案二更适合中大型项目,便于后续扩展不同的布局模板。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 05:36:13