代码Sandbox

https://codesandbox.io/s/patches-xy8h2l?file=/src/components/Support/Products/index.js

通过转到"此处访问驱动程序系统"->所有产品->SuperServerLine重新解决此问题

问题是,当页面使用不同的URL重新呈现时,fetchProducts应该重新运行.根据提供的路由参数(productLineserver),将运行fetchProducts的不同部分.然而,无论您访问什么URL,这些都始终是未定义的.工作意味着它应该打印三台服务器:"你做到了1"、"胜利2"和"它正在工作3".

您可以通过以下方式更改支持组件来解决该问题:

import { Helmet } from "react-helmet";
import { Route, Routes } from "react-router-dom";
import Products from "./Products";
import Product from "./Product";
import Dashboard from "../Admin/Dashboard";
import XmlDetails from "./Products/XmlDetails";
import "./style.css";

function Support() {
  return (
    <div className="App">
      <Helmet>
        <title>Product Support | Dell US</title>
      </Helmet>
      <Routes>
        <Route
          path="products/:category?/*"
          element={
            <div className="support-products">
              <Products />
            </div>
          }
          exact
        />
        <Route path=":category/:device" element={<Product />} />
        <Route path="dashboard" element={<Dashboard />} />
        <Route path="catalogs" element={<XmlDetails />} />
      </Routes>
    </div>
  );
}

export default Support;

然而,这会 destruct 路由的其他方面.我不清楚为什么参数不能按原样工作.

父组件(Support/index.js)

import { Helmet } from "react-helmet";
import { Route, Routes } from "react-router-dom";
import Products from "./Products";
import "./style.css";

function Support() {
  return (
    <div className="App">
      <Helmet>
        <title>Product Support</title>
      </Helmet>
      <Routes>
        <Route
          path="products/*"
          element={
            <div className="support-products">
              <Products />
            </div>
          }
          exact
        />
      </Routes>
    </div>
  );
}

export default Support;

子组件(Support/Products/index.js)

import React, { useState, useEffect } from "react";
import {
  NavLink,
  Link,
  Route,
  Routes,
  useParams,
  useLocation
} from "react-router-dom";
import http from "../../http";
import { strCompare } from "../../util";
import "./style.css";
import Alert from "react-bootstrap/Alert";

function Products() {
  // Here, 'ProductLine' might be something like "SuperServerLine" or "server 2",
  // and 'server' could be something like "server 3".
  const { productLine, server } = useParams(); // <- Example values for productLine and server
  const location = useLocation();
  const [productLines, setProductLines] = useState([]);
  const [servers, setServers] = useState([]);
  const [authorized, setAuthorized] = useState(null);
  console.log("productLine:", productLine); // Debugging line
  console.log("server:", server); // Debugging line

  useEffect(() => {
    if (location.state !== undefined && location.state !== null) {
      setAuthorized(location.state.authorized);
    }

    const fetchProducts = async () => {
      if (!productLine) {
        try {
          const res = await http.get("/api/brands");
          if (res.brands.length === 0) {
            alert("No product lines available");
          } else {
            setProductLines(res.brands.sort());
          }
        } catch (error) {
          console.error("Failed to fetch product lines:", error);
        }
        // If there's a productLine (e.g., "SuperServerLine") but no specific server (e.g., "server 1"),
        // fetch the systems for that productLine.
      } else if (productLine && !server) {
        // The endpoint will include the productLine value (e.g., "/api/systems?brand=SuperServerLine").
        try {
          const res = await http.get("/api/systems?brand=" + productLine);
          if (res.systems.length === 0) {
            alert("No servers for this product available");
          } else {
            res.systems.sort((a, b) => strCompare(a.system_id, b.system_id));
            // setServers(res.systems); REMOVING FOR MOCK
            setServers(mockServers);
          }
        } catch (error) {
          console.error("Failed to fetch servers:", error);
        }
      }
    };

    fetchProducts();
  }, [productLine, server, location.state]);

  const getBreadCrumbs = () => {
    let path = location.pathname.split("/").filter(Boolean);
    let crumbs = [];
    crumbs.push({ label: "All " + path[0], path: `/${path[0]}/` });
    for (let i = 1; i < path.length; i++) {
      if (path[i]) {
        crumbs.push({
          label: path[i],
          path: `${crumbs[i - 1].path}${path[i]}/`
        });
      }
    }
    return crumbs;
  };

  return (
    <div className="products-content container">
      <div className="container-fluid">
        <div className="row">
          <div className="col-xs-6">
            {authorized === false && (
              <div className="error-box">
                <Alert variant="danger">
                  Please contact administrator for access to admin page
                </Alert>
              </div>
            )}
          </div>
        </div>
      </div>

      <div className="product-nav">
        {getBreadCrumbs().map((crumb) => {
          return (
            <div key={crumb.label}>
              <NavLink to={crumb.path} className="breadcrumb-active" end>
                {crumb.label}
              </NavLink>
              <span className="breadcrumb-delim">/</span>
            </div>
          );
        })}
      </div>
      <div>
        <Routes>
          <Route
            path="/"
            element={
              <ListProductLines productLines={["SuperServerLine"]} exact />
            }
          />
          <Route
            path=":productLine"
            element={<ListServers servers={servers} />}
          />
          <Route path=":productLine/:server*" element={<div>We made it</div>} />
        </Routes>
      </div>
    </div>
  );
}

// Component to render a list of product lines SuperServerLine, etc
function ListProductLines({ productLines }) {
  return (
    <div className="product-links row">
      {/* Map over the 'productLines' array and render each product */}
      {productLines.map((prod, i) => (
        <div key={i} className="component-link col-xs-12 col-md-3">
          {/* Create a link to the product page using 'renderProductName' to form the URL */}
          <Link to={`/products/${prod}`}>
            {/* Display the product name using 'renderProductName' */}
            {prod}
          </Link>
        </div>
      ))}
    </div>
  );
}

// Function to render a list of products for a specific productLine, e.g., servers R440, R7625, etc.
function ListServers({ servers }) {
  return (
    <div className="product-links row">
      {servers.map((prod, i) => {
        return (
          <div key={i} className="component-link col-xs-12 col-md-3">
            <Link to={`./${prod.system_id}/drivers`}>
              {`${prod.brand} ${prod.name}`}
            </Link>
          </div>
        );
      })}
    </div>
  );
}

const mockServers = [
  {
    system_id: "05CE",
    system_id_type: "MULTISYSTEMCHASSIS",
    brand: "SuperServerLine",
    name: "Server 1",
    created_at: "2023-08-16T17:59:22.249Z",
    updated_at: "2023-08-16T17:59:22.249Z"
  },
  {
    system_id: "05CF",
    system_id_type: "MULTISYSTEMCHASSIS",
    brand: "SuperServerLine",
    name: "Server 2",
    created_at: "2023-08-16T17:59:22.249Z",
    updated_at: "2023-08-16T17:59:22.249Z"
  },
  {
    system_id: "05D0",
    system_id_type: "MULTISYSTEMCHASSIS",
    brand: "SuperServerLine",
    name: "Server 3",
    created_at: "2023-08-16T17:59:22.249Z",
    updated_at: "2023-08-16T17:59:22.249Z"
  }
];

export default Products;

推荐答案

Routes组件似乎不能读取任何后代Routes组件的任何动态路由路径段(e.g. routed components rendering another set of 100 and 103 components).Routes可以读取它正在渲染的any条路径的路径参数,任何带有尾随"*"(splat)个通配符匹配符的路径都将简单地将"路径的其余部分"放在一个Splat参数上.

例如,如果路由的路径是"/:test/*",而当前URL路径是"/segment1/segment2/segment3",则以下是可访问的内容:

const { test, "*": splat } = useParams();
console.log(test);  // "segment1"
cons至l.log(splat); // "segment2/segment3"

Products"/products/*"上呈现,因此这意味着任何更深嵌套的路由都将显示在屏幕上.您可以进行一些简单的字符串拆分和数组解构赋值,以获得productLineserver路径段值.

更新Product

const { productLine, server } = useParams();

const { "*": splat } = useParams();
const [productLine, server] = splat.split("/");

Edit reactjs-nested-route-will-not-render

Javascript相关问答推荐

Angular 拦截器错误处理删除方法问题

React状态变量在使用++前置更新时引发错误

用户单击仅在JavaScript中传递一次以及其他行为

为什么JavaScript双边字符串文字插值不是二次的?

微软Edge Select 间隙鼠标退出问题

使用续集和下拉栏显示模型属性

硬币兑换运行超时

单击子元素时关闭父元素(JS)

扫描qr code后出错whatter—web.js

如何修复我的js构建表每当我添加一个额外的列作为它的第一列?

为什么!逗号和空格不会作为输出返回,如果它在参数上?

在SHINY R中的嵌套模块中,不能使用Java代码

如果没有页面重新加载Angular ,innerHTML属性绑定不会更新

使用jQuery find()获取元素的属性

如何组合Multer上传?

如何根据输入数量正确显示alert ?

P5JS-绘制不重叠的圆

如果我的列有条件,我如何呈现图标?

将Singleton实例设置为未定义后的Angular 变量引用持久性行为

Django模板中未加载JavaScript函数