kitze / mobx-router

A simple router for MobX + React apps
509 stars 66 forks source link

Is it possible to do nested routing? #95

Closed harrycollin closed 4 years ago

harrycollin commented 4 years ago

I was looking for a way to do nested routing without having to define lots of top level routes. Is there an example for this?

thdk commented 4 years ago

Hi, can you give an example of what you are trying to accomplish? What do you mean with "without having to define lots of top level routes"?

harrycollin commented 4 years ago

Hi @thdk, so what's the best way to offload the responsibility for all routes under /dashboard/* instead of having to define multiple routes likes '/dashboard/reports' and '/dashboard/profile' etc. In my case all routes under /dashboard are supposed to be rendered with the same container but have different content.

This is how I currently have to map the sub-routes of /dashboard. It isn't very convenient.

const routes = {
    dashboard: new Route({
        path: '/dashboard',
        component: <Dashboard/>,
        onEnter: () => {
            console.log('entering user dashboard!');
        },
        beforeExit: () => {
            console.log('exiting user dashboard!');
        },
        onParamsChange: (route, params, store) => {
            console.log('params changed to', params);
        }
    }),
    dashboardReports: new Route({
        path: '/dashboard/reports',
        component: <Dashboard reports={true} />,
        onEnter: () => {
            console.log('entering user dashboard reports!');
        },
        beforeExit: () => {
            console.log('exiting user dashboard reports!');
        },
        onParamsChange: (route, params, store) => {
            console.log('params changed to', params);
        }
    })
};

Is there a better way to do this? I know this is possible in react-router by using multiple 's.

harrycollin commented 4 years ago

I understand that you can have '/dashboard/:tab' for example to handle sub-routes at a top level, but is there a way to use a route object structure as above for nested routes?

thdk commented 4 years ago

Can you write the same route config for /dashboard and /dashboard/reports as above as how you would like to see it?

harrycollin commented 4 years ago

I would imagine it would work something like this.

const topRoutes= {
    dashboard: new Route({
        path: '/dashboard',
        component: <Dashboard/>,
        onEnter: () => {
            console.log('entering dashboard!');
        },
        beforeExit: () => {
            console.log('exiting dashboard!');
        },
        onParamsChange: (route, params, store) => {
            console.log('params changed to', params);
        }
    })
};

startRouter(topRoutes, store);

function App() {
    return <MobxRouter store={store}/>
}
const dashboardRoutes= {
     dashboardHome: new Route({
        path: '/',
        component: <Home/>,
        onEnter: () => {
            console.log('entering dashboard!');
        },
        beforeExit: () => {
            console.log('exiting dashboard!');
        },
        onParamsChange: (route, params, store) => {
            console.log('params changed to', params);
        }
    }),
    reports: new Route({
        path: '/reports',
        component: <Reports/>,
        onEnter: () => {
            console.log('entering dashboard reports!');
        },
        beforeExit: () => {
            console.log('exiting dashboard settings!');
        },
        onParamsChange: (route, params, store) => {
            console.log('params changed to', params);
        }
    }),
    settings: new Route({
        path: '/settings',
        component: <Settings/>,
        onEnter: () => {
            console.log('entering dashboard settings!');
        },
        beforeExit: () => {
            console.log('exiting dashboard settings!);
        },
        onParamsChange: (route, params, store) => {
            console.log('params changed to', params);
        }
    })
};

startRouter(dashboardRoutes, store);

function Dashboard() {
    return (
       <SomeContainerElement>
          <MobxRouter basePath='/dashboard' store={store}/>
       </SomeContainerElement>
    )
}

A proposed 'basePath' prop would indicate that it should only look for routes with that prop prefixed.

Does this seem like a reasonable thing to do?

thdk commented 4 years ago

Ok, I see. That way you would have more than one instance of MobxRouter which is not supported.

Is your question how you can move configuration of child routes into another file?

If so you can do something like:

project
   -routes
        index.ts
   -dashboard
        routes
        dashboardpage
        dashboardcomponents
   -anothertoplevel
        routes
        anotherpage
        anothercomponents

where your routes/index.ts simply gathers all routes config from all top level configuration files.

const root = {
  root: new Route({
    path: '/',
    component: <App></App>,
  })
};

import {dashboardRoutes } from "../dashboard/routes";
import {anotherRoutes} from "../anothertoplevel/routes";

export const routes = {
  ...root,
  ...dashboardRoutes,
  ...anotherRoutes,
};

I'm using such a setup in my project here: https://github.com/thdk/timesheets/blob/develop/src/routes/index.tsx

Would this help your any further?

harrycollin commented 4 years ago

@thdk Thank you, this is very useful! This solves my issue in a way :)