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

React Router路由优化:点击店铺卡片后隐藏父组件仅显导航栏

React Router 路由跳转后父组件内容未隐藏的解决方案

开发背景

我开发了一个简单的React应用,从MongoDB数据库中获取HM、Amazon、Lindex等不同店铺的数据,并以带链接的卡片形式展示(核心逻辑在Boutiques.js中)。

期望效果

点击任意卡片后通过React Router跳转到对应页面:

  • 点击“HM”卡片跳转到/boutiques/HM,仅渲染导航栏和Template组件,隐藏店铺卡片列表
  • 点击“Amazon”卡片跳转到/boutiques/Amazon,逻辑同上

当前问题

点击卡片后,Template组件会直接渲染在店铺卡片下方,原有的卡片列表仍会显示,无法实现“仅显示导航栏和目标页面”的效果。

现有代码

App.js

import { BrowserRouter, Link, Route, Routes } from "react-router-dom";
import React from "react";
import "./CouponDeals.css";
import Boutiques from "./Boutiques";
import Home from './Home';

function App() {
  return (
    <BrowserRouter>
      <div className="main-container">
        <div className="navbar-section-container">
          <div class="navbar">
            <Link to="/">Hem</Link>
            <Link to="/boutiques">Butiker</Link>
          </div>
        </div>
        <Routes>
          <Route exact path="/" element={<Home />} />
          <Route path="/boutiques/*" element={<Boutiques />} />
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

Boutiques.js

import React, { useEffect, useState } from "react";
import {Link, Route, Routes } from "react-router-dom";
import axios from "./Axios";
import Template from "./Template.js";

const Boutiques = () => {
  const [deals, setDeals] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const req = await axios.get("/butiker");
      setDeals(req.data);
    }

    fetchData();
  }, []);
  return (
    <React.Fragment>
      <div className="header-section">
        <h1 className="title">All Boutiques</h1>
      </div>
      <div className="card-section-container">
        <div className="deals-container">
          {deals.length > 0 ? (
            deals.map((deal, index) => (
              <div key={index} className="deal">
                <div className="button-container">
                  <Link to={`${deal.name}`} className="butiker-button">
                    <img src={deal.imgUrl} alt={deal.name} />
                  </Link>
                </div>
              </div>
            ))
          ) : (
            <p className="no-results">No results found</p>
          )}
        </div>
      </div>
      <Routes>
        {deals.map((deal, index) => (
          <Route
            key={index}
            path={`${deal.name}`}
            element={<Template name={deal.name} />}
          />
        ))}
      </Routes>
    </React.Fragment>
  );
};

export default Boutiques;

重构方案

核心思路是将Boutiques组件拆分为路由容器和列表展示组件,通过嵌套路由的逻辑控制不同路径下的内容渲染。

步骤1:拆分列表展示组件

创建BoutiquesList.js,将原Boutiques中的店铺卡片列表逻辑独立出来:

import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import axios from "./Axios";

const BoutiquesList = () => {
  const [deals, setDeals] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const req = await axios.get("/butiker");
      setDeals(req.data);
    }

    fetchData();
  }, []);
  
  return (
    <>
      <div className="header-section">
        <h1 className="title">All Boutiques</h1>
      </div>
      <div className="card-section-container">
        <div className="deals-container">
          {deals.length > 0 ? (
            deals.map((deal, index) => (
              <div key={index} className="deal">
                <div className="button-container">
                  <Link to={`${deal.name}`} className="butiker-button">
                    <img src={deal.imgUrl} alt={deal.name} />
                  </Link>
                </div>
              </div>
            ))
          ) : (
            <p className="no-results">No results found</p>
          )}
        </div>
      </div>
    </>
  );
};

export default BoutiquesList;

步骤2:修改Boutiques为路由容器

将原Boutiques组件改为仅负责嵌套路由的渲染,不再直接显示列表:

import React, { useEffect, useState } from "react";
import { Route, Routes } from "react-router-dom";
import axios from "./Axios";
import Template from "./Template.js";
import BoutiquesList from "./BoutiquesList";

const Boutiques = () => {
  const [deals, setDeals] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const req = await axios.get("/butiker");
      setDeals(req.data);
    }

    fetchData();
  }, []);
  
  return (
    <Routes>
      {/* 访问/boutiques时,渲染店铺列表 */}
      <Route index element={<BoutiquesList />} />
      {/* 访问/boutiques/[店铺名]时,渲染对应Template */}
      {deals.map((deal, index) => (
        <Route
          key={index}
          path={`${deal.name}`}
          element={<Template name={deal.name} />}
        />
      ))}
    </Routes>
  );
};

export default Boutiques;

优化方案:使用动态路由参数

如果不想依赖后端返回的店铺数据生成路由,可以改用动态参数路由,这样无需等待数据加载即可匹配路径:
修改Boutiques组件的路由部分:

<Routes>
  <Route index element={<BoutiquesList />} />
  {/* 动态匹配任意店铺名称 */}
  <Route path=":boutiqueName" element={<Template />} />
</Routes>

然后在Template组件中通过useParams获取店铺名称:

import { useParams } from "react-router-dom";

const Template = () => {
  const { boutiqueName } = useParams();
  return <div>{boutiqueName}专属页面</div>;
};

export default Template;

效果验证

  • 访问/boutiques:显示导航栏+店铺卡片列表
  • 点击任意卡片跳转到/boutiques/[店铺名]:仅显示导航栏+对应Template组件,原列表自动隐藏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:35:17