使用反应路由器的动态面包屑

时间:2016-02-01 08:59:56

标签: reactjs react-router

如何制作breadcrumbs on site in examples folder of react-router repo有很好的例子。但我想知道如何用动态路线制作面包屑。

假设我们有这样的配置:

ReactDOM.render((
<Router history={browserHistory}>
    <Route path="/projects" component={ProjectsApp}>
        <IndexRoute component={ProjectsDashboard} />
        <Route path=":projectId" component={ProjectBoard}>
            <Route path=":taskId" component={ProjectTaskBoard}>
        </Route>
    </Route>
</Router>
), document.getElementById('app'));

我想做这样的事情:

项目(链接到'/ projects') - &gt; MyAwesomeProject(链接到'/ projects / 11'。从某处获取的标题(来自storeParams的id或其他方式的商店) - &gt; MyTask(链接到'/ projects / 11/999')

我怎样才能达到这个效果?有没有最佳做法?感谢。

5 个答案:

答案 0 :(得分:5)

我们使用最为

的包react-breadcrumbs-dynamic

适用于任何路由器(包括react-router v4)。

import {
  BreadcrumbsProvider,
  Breadcrumbs,
  BreadcrumbsItem
} from 'react-breadcrumbs-dynamic'

const theApp = (
  <BreadcrumbsProvider>
    <App />
  </BreadcrumbsProvider>
)

const App = (props) => (
  return (
    <div className="App">
      <Breadcrumbs/>
      {props.children}
    </div>
  )
}

const Page = (props) => (
  <div>
    <BreadcrumbsItem to='/'>Main Page</BreadcrumbsItem>
    {props.children}
    <Route exact path="/user" component={User} />
  </div>
)


const User = (props) => (
  <div>
    <BreadcrumbsItem to='/user'>Home</BreadcrumbsItem>
    <h2>Home</h2>
  </div>
)

回购在这里:react-breadcrumbs-dynamic

答案 1 :(得分:2)

  

使用react-router v4,所有路由都是动态的(虽然我认为仍然有编写静态定义的选项)。

正如@tbo在评论中所提到的,react-breadcrumbs是一个很好的解决方案,用于实现反应路由器版本3。您描述的动态面包屑甚至有一些变通方法(例如使用prependgetDisplayName道具)。

in this issue正在进行一次对话,以确定如何最好地支持react-router v4,这肯定与你的问题有关。我已经挖掘了一堆其他面包屑组件库,这些存储库看起来都很难解决相同的静态路由问题,有些类似的问题已经打开以确定v4支持。

TLDR;如果您仍在使用react-router v3,则可以使react-breadcrumbs包适用于动态面包屑。如果您已迁移到v4,请继续关注,我希望很快会有更好的答案。

<强>更新

在找不到符合我需求的其他解决方案后,我开发了一个解决方案并在react-breadcrumbs存储库上打开了pull requestAuto-breadcrumb,如下所述,this discussion也是潜在的解决方案,但允许更少的自定义。如果您需要更多自定义,请订阅并随意评论或帮助pr。

答案 2 :(得分:1)

如果您使用的是React Router的第4版,

Auto-Breadcrumb似乎是最佳选择。我还没有找到一个很好的教程,但是有一个没有注释,但是公平simple demo可用。

答案 3 :(得分:1)

这是为嵌套导航和面包屑提供单一事实来源的解决方案。

该示例应用程序可在GitHub上使用:https://github.com/sneas/react-nested-routes-example

演示:https://sneas.github.io/react-nested-routes-example/

导航配置:

export const navigation = [
  {
    path: "/",
    label: "All categories",
    content: () => <AllCategories />,
    routes: [
      {
        path: "/electronics",
        label: "Electronics",
        content: () => <Electronics />,
        routes: [
          {
            path: "/accessories",
            label: "Accessories",
            content: () => <Accessories />,
            routes: [
              {
                path: "/usb-cables",
                label: "USB cables",
                content: () => <UsbCables />
              }
            ]
          },
          {
            path: "/headphones",
            label: "Headphones",
            content: () => <Headphones />
          }
        ]
      }
    ]
  }
];

我们必须递归地展平导航并将其呈现为平面数组:

const routes = flattenRoutes(navigation);
return (<Router>
  {routes.map((route, index) => (
    <Route
      key={index}
      path={route.path}
      render={() => rouete.content}
    ></Route>
  ))}
</Router>);

然后使用相同的导航结构构建面包屑。

答案 4 :(得分:0)

有几种方法可以做到这一点,还有几种开源解决方案(请参阅此处的答案:How do I create react-router v4 breadcrumbs?

就个人而言,我更喜欢HOC解决方案,因为它具有较小的表面积,渲染灵活性和可读的痕迹路径配置。

Breadcrumbs.jsx

import React from 'react';
import { NavLink } from 'react-router-dom';
import { withBreadcrumbs } from 'withBreadcrumbs';

const UserBreadcrumb = ({ match }) =>
  <span>{match.params.userId}</span>; // use match param userId to fetch/display user name

const routes = [
  { path: 'users', breadcrumb: 'Users' },
  { path: 'users/:userId', breadcrumb: UserBreadcrumb},
  { path: 'something-else', breadcrumb: ':)' },
];

const Breadcrumbs = ({ breadcrumbs }) => (
  <div>
    {breadcrumbs.map(({ breadcrumb, path, match }) => (
      <span key={path}>
        <NavLink to={match.url}>
          {breadcrumb}
        </NavLink>
        <span>/</span>
      </span>
    ))}
  </div>
);

export default withBreadcrumbs(routes)(Breadcrumbs);

withBreadcrumbs.js

import React from 'react';
import { matchPath, withRouter } from 'react-router';

const renderer = ({ breadcrumb, match }) => {
  if (typeof breadcrumb === 'function') { return breadcrumb({ match }); }
  return breadcrumb;
};

export const getBreadcrumbs = ({ routes, pathname }) => {
  const matches = [];

  pathname
    .replace(/\/$/, '')
    .split('/')
    .reduce((previous, current) => {
      const pathSection = `${previous}/${current}`;

      let breadcrumbMatch;

      routes.some(({ breadcrumb, path }) => {
        const match = matchPath(pathSection, { exact: true, path });

        if (match) {
          breadcrumbMatch = {
            breadcrumb: renderer({ breadcrumb, match }),
            path,
            match,
          };
          return true;
        }

        return false;
      });

      if (breadcrumbMatch) {
        matches.push(breadcrumbMatch);
      }

      return pathSection;
    });

  return matches;
};

export const withBreadcrumbs = routes => Component => withRouter(props => (
  <Component
    {...props}
    breadcrumbs={
      getBreadcrumbs({
        pathname: props.location.pathname,
        routes,
      })
    }
  />
));

这里也提供开源HOC: https://github.com/icd2k3/react-router-breadcrumbs-hoc