universal-router icon indicating copy to clipboard operation
universal-router copied to clipboard

Example of breadcrumbs?

Open richb-hanover opened this issue 9 years ago • 9 comments

I'd like to have breadcrumbs for my site. Does anyone have recommendations for implementing them as part of universal-router? Thanks.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/36212127-example-of-breadcrumbs?utm_campaign=plugin&utm_content=tracker%2F18115217&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F18115217&utm_medium=issues&utm_source=github).

richb-hanover avatar Jul 21 '16 01:07 richb-hanover

I personally like this approach:

Route

{
  path: '/about',
  action() {
    return <AboutPage />; // or, return { title: 'About Us', component: <AboutPage /> }
  }
}

Component

import React from 'react';
import Layout from '../components/Layout';

class AboutPage extends React.Component {
  render() {
    return (
      <Layout breadcrumbs="Home > About">
        <h1>About Us</h1>
        <p>Bla-bla-bla</p>
      </Layout>
    );
  }
}

export default AboutPage;

In the example above, the breadcrumbs prop is just a string, but it could be a React component or an array.

koistya avatar Jul 21 '16 02:07 koistya

I'm trying to look for automatic breadcrumb with the same example but having nested routes using children - any ideas?

ex: /teams/:teamId -> parent route /teams/:teamId/projects/:projectId/ -> child route /teams/:teamId/projects/:projectId/panel1 -> child route

Thanks.

tamer-mohamed avatar Jan 22 '17 13:01 tamer-mohamed

@tamerelsayed since v3.0.0 you can do like so:

import Router from 'universal-router';

const routes = {
  path: '/teams/:teamId',
  title: 'Team',
  children: [
    {
      path: '/projects/:projectId',
      title: 'Project',
      children: [
        {
          path: '/panel1',
          title: 'Panel',
          page: 'Panel Page',
        },
      ],
    },
  ],
};

const options = {
  resolveRoute(context) {
    return context.route.page ? context : null;
  }
};

const router = new Router(routes, options);

router.resolve('/teams/1/projects/1/panel1').then(context => {
  console.log(context);
  const breadcrumbs = [];
  let route = context.route;
  while (route) {
    breadcrumbs.push(route.title);
    route = route.parent;
  }

  document.body.innerHTML =
    `<h1>${context.route.title}</h1>` +
    `<p>Breadcrumbs: ${breadcrumbs.reverse().join(' → ')}</p>` +
    `<p>Content: ${context.route.page}</p>`;
  // => <h1>Panel</h1>
  // => <p>Breadcrumbs: Team → Project → Panel</p>
  // => <p>Content: Panel Page</p>
});

Playground: https://jsfiddle.net/frenzzy/qL66ok9h/

frenzzy avatar Mar 25 '17 21:03 frenzzy

@frenzzy how could I get the value of breadcrumbs array to render, thanks 😄

@young666 like in the example above? Or if you need this on route level:

const route = {
  path: '/users',
  title: 'Users',
  action(context) {
    const breadcrumbs = [];
    let route = context.route;
    while (route) {
      breadcrumbs.unshift(route.title);
      route = route.parent;
    }
    console.log(breadcrumbs) // => ['Users']
  }
}

frenzzy avatar Jul 31 '18 08:07 frenzzy

@frenzzy my problem is that resolve return only Promise, I can't get the value inside then() like this:

render() {
  const BreadcrumbItems = [];
  const router = new UniversalRouter(route, options);
  router.resolve(pathname).then(context => {
    /* loop to push context.route.title into BreadcrumbItems */
  });

  // Here's a new BreadcrumbItems get well-prepared to be rendered but it didn't :(
  return BreadcrumbItems.map(item => (<span>{item}<span>));
}

What is render() in your example, a method of a react component? React's render method is sync, but router.resolve is async. You can't use async staff in the render method of a react component because React.js does not support it. Otherwise just put breadcrumbs logic into then and return the promise.

frenzzy avatar Jul 31 '18 10:07 frenzzy

I'm using react-starter-kit, the pathname variable I only could get it from react context: const { pathname } = this.context;. I want to create a breadcrumbs component by resolving route based on pathname. But this seems to be impossible. I may try to find another way 😞

In react-starter-kit you may patch resolveRoute function to access breadcrumbs in all routes:

resolveRoute(context, params) {
  const breadcrumbs = []
  let route = context.route
  while (route) {
    breadcrumbs.unshift(route.title)
    route = route.parent
  }
  context.breadcrumbs = breadcrumbs // <=
  // ...
}

frenzzy avatar Jul 31 '18 10:07 frenzzy