Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of breadcrumbs? #36

Open
richb-hanover opened this issue Jul 21, 2016 · 9 comments · May be fixed by #86
Open

Example of breadcrumbs? #36

richb-hanover opened this issue Jul 21, 2016 · 9 comments · May be fixed by #86

Comments

@richb-hanover
Copy link

richb-hanover commented Jul 21, 2016

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).
@koistya
Copy link
Member

koistya commented Jul 21, 2016

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.

@tamer-mohamed
Copy link

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.

@frenzzy
Copy link
Member

frenzzy commented Mar 25, 2017

@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 frenzzy linked a pull request Mar 26, 2017 that will close this issue
20 tasks
@taily-khucnaykhongquantrong

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

@frenzzy
Copy link
Member

frenzzy commented Jul 31, 2018

@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']
  }
}

@taily-khucnaykhongquantrong
Copy link

taily-khucnaykhongquantrong commented Jul 31, 2018

@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>));
}

@frenzzy
Copy link
Member

frenzzy commented Jul 31, 2018

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.

@taily-khucnaykhongquantrong
Copy link

taily-khucnaykhongquantrong commented Jul 31, 2018

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 😞

@frenzzy
Copy link
Member

frenzzy commented Jul 31, 2018

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 // <=
  // ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants