【问题标题】:How to use map function with react router?如何在反应路由器中使用地图功能?
【发布时间】:2022-01-03 19:19:56
【问题描述】:

我有一个 pageNames 列表和一个 pageUrls 列表。我想创建一个路由器,为列表中的每个页面生成一个反应组件,并使用带有路由器链接的导航栏。我认为问题出在 forEach 函数上,但我不确定。

谁能告诉我我做错了什么?

虽然我觉得它没有帮助,here is a similar question

import React, { useState } from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";

function App() {

  const routes = [
    {
      name: 'home',
      path: '/'
    },
    {
      name: 'blog',
      path: '/blog'
    }
  ]

  // translate (map) your array of objects into jsx
  const routeComponents = routes.map(({name, path}) => ((
    <Route key={name} path={path}>
      <h1>{name}</h1>
    </Route>
  )))
  
  return (
    <div className="App" >
      <Router>
        <Navbar routes = {routes} />
        <Switch>
          {routeComponents}          
        </Switch>
      </Router>
    </div>
  );
}

export default App;

function Navbar(props){
  const links = props.routes.map(({name, path}) => (
    <Link key={name} to={path}>{name}</Link>
  ))
    return(
        <div style={{justifyContent: "space-around", margin:"auto", display:"flex",justifyContent:"space-around",backgroundColor:"red"}}>
            {links}
        </div>
    )
}

【问题讨论】:

    标签: reactjs react-router react-router-dom


    【解决方案1】:

    您可能看到的问题是由Switch 组件的工作方式引起的。它呈现第一个匹配RouteRedirect 组件。这意味着在Switch 组件路径中的顺序和特异性很重要!主路径"/" 匹配任何路径,因此总是会被匹配和渲染。

    您可以通过将路由从更具体到不太具体重新排序来避免这种情况,或者由于您暗示希望路由从用户交互中动态生成并存储在某个状态中,因此请为所有路由指定 exact 属性匹配发生完全并且顺序和特异性被否定。

    function App() {
      const routes = [
        {
          name: 'home',
          path: '/',
        },
        {
          name: 'blog',
          path: '/blog',
        },
      ];
    
      const routeComponents = routes.map(({name, path}) => (
        <Route key={name} exact path={path}> // <-- exact prop to exactly match paths
          <h1>{name}</h1>
        </Route>
      ));
      
      return (
        <div className="App" >
          <Router>
            <Navbar routes={routes} />
            <Switch>
              {routeComponents}          
            </Switch>
          </Router>
        </div>
      );
    }
    

    【讨论】:

      【解决方案2】:

      你是对的。 forEach 正在填充您的 routes 变量,这是一个数组。你想要的是构建一些 JSX。这通常通过map 完成。您也不需要 useState 调用,您需要将页面名称和 url 合并到一个对象中以便于管理。

      这里有一些伪代码会让你走上正轨……

        const routes = [
          {
            name: 'hello',
            path: '/'
          },
          {
            name: 'there',
            path: '/there'
          }
        ]
      
        // translate (map) your array of objects into jsx
        const routeComponents = routes.map(({name, path}) => (
          <Route key={name} path={path}/>
        ))
      
        // routeComponents is JSX. You originally had an array of JSX
        <Switch>
          {routeComponents}          
        </Switch>
      
        // Same thing for your links
        const navbar = routes.map(({name, path}) => (
          <Link key={name} to={path}>{name}</Link>
        ))
      
        <div>
          {navbar}          
        </div>
      

      更新 上面示例中的一些调整以澄清它。

      更新 #2 这是完整的代码(卡在 1 个文件中)。 更新为响应路由器 v6。 test it here

      import "./styles.css";
      
      import React, { useState } from "react";
      import {
        BrowserRouter as Router,
        Routes,
        Route,
        Link,
        Outlet
      } from "react-router-dom";
      
      function Navbar({ routes }) {
        const links = routes.map(({ name, path }) => (
          <Link key={name} to={path}>
            {name}
          </Link>
        ));
        return (
          <div
            style={{
              justifyContent: "space-around",
              margin: "auto",
              display: "flex",
              justifyContent: "space-around",
              backgroundColor: "red"
            }}
          >
            {links}
          </div>
        );
      }
      
      export default function App() {
        const routes = [
          {
            name: "home",
            path: "/"
          },
          {
            name: "blog",
            path: "/blog"
          },
          {
            name: "about",
            path: "/about"
          }
        ];
      
        // translate (map) your array of objects into jsx
        const routeComponents = routes.map(({ name, path }) => (
          <Route key={name} path={path} element={<h1>{name}</h1>} />
        ));
      
        return (
          <div className="App">
            <h1>Hello CodeSandbox</h1>
            <h2>Start editing to see some magic happen!</h2>
            <Router>
              <Routes>{routeComponents}</Routes>
              <Navbar routes={routes} />
            </Router>
            {Outlet}
          </div>
        );
      }
      

      【讨论】:

      • 这看起来很棒,戴夫。我真的很想使用“useState”,因为我计划使路由器动态化,以便用户可以添加/删除页面。如果路由对象由“useState”管理,上述答案是否有效?
      • 是的,您可以在 useEffect 中获取您的路线并将它们保存到路线状态。但不要管理 2 个状态(名称和 url)。每个路由都是一个以 name/url 作为键的对象。所以 [routes, setRoutes] = useState() 当你知道它们是什么时,在 useEffect() 中调用 setRoutes() 到你的路由。类似的东西...
      • 戴夫,很抱歉未能接受您的回答。使用您的修改仍然给我同样的问题。标题不会从“home”更改。
      • 您为“链接”编写的代码是正确的。对你的“路线”做同样的事情。问题是您的代码中的 {routes} 是一个数组。如果还有其他问题,则在路由/链接代码中。
      • 我已经更新了我的代码,以便将地图功能用于路线。它仍然具有相同的行为。我认为还有其他问题。
      猜你喜欢
      • 1970-01-01
      • 2016-08-29
      • 2019-10-02
      • 2019-06-02
      • 1970-01-01
      • 2020-01-04
      • 2021-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多