frontarm / navi

🧭 Declarative, asynchronous routing for React.
https://frontarm.com/navi/
MIT License
2.07k stars 71 forks source link

How to access the routes tree? Creating breadcrumbs and more #178

Open OnkelTem opened 4 years ago

OnkelTem commented 4 years ago

I wonder how to can I access routes tree?

For exampe, I would like to store some information in the routes definition:

  mount({
    "/section/route1": route({
      title: "Route 1 title",
      data: {myData: 'route1 data'},
      view: <Route1View/>
    }),
    "/section/route2": route({
      title: "Route 2 title",
      data: {myData: 'route2 data'},
      view: <Route2View/>
    }),
    // ...
  })

Now how can I access this tree to build breadcrumbs or to parametarize other components?

I can think of two places where I would like to have that: route definition and component. But I don't want to make my components navi-aware, so the proper location should be still the Navi contraptions, e.g. withView() body:

  "/section": compose(
    withView((request, context) => {
      const breadcrumbs = buildBreadcrumns(getRoutesTree()); // <== breadcrumbs
      const myData = buildMyData(getRoutesTree())[request.path]; // <== data
      return (
        <SectionView breadcrumbs={breadcrumbs} data={myData}>
          <View/>
        </SectionView>
      )
    }),
    mount(...)
  ),

I wonder what can I use in place of the getRoutesTree() imaginary function from above?

OnkelTem commented 4 years ago

@jamesknelson Would you please have a look at this?

OnkelTem commented 4 years ago

Let me clearify what I mean: how to access the current routes tree? In other words, how to fetch all route objects back to create navigation menus or breadcrumbs? I don't want to duplicate the whole tree elsewhere. For instance, with react-router or reach-router I can easily fetch their routes and build breadcrumbs.

jamesknelson commented 4 years ago

So one of the key design constraints for Navi is that each matcher should be able to run independently of the previous matchers, so that they can run simultaneously. The only exception to this is the withContext matcher, which must run before any subsequent matchers.

Because of this, the only way a matcher can depend on data from further up the tree, is if that data is in context. So, if you'd like to to do something like this, currently you'll need to specify the data that you want to pass down using withContext matchers.

I've got some ideas on an improved way to do this, but they're a little ways off of production support unfortunately.