Skip to content

groupRoutes ​

Route group factory.
Returns a RouteGroup β€” a container that gives a set of routes a shared isOpened and a default child (indexRoute) for group.open(). Class form: new RouteGroup().

Usage ​

ts
groupRoutes(routes, indexRoute?)
new RouteGroup(routes, indexRoute?)

Accepts an object of routes and nested groups β€” Route, RouteGroup, or VirtualRoute.

Optional indexRoute sets the default child explicitly (overrides auto-detection by index: true on a child).

Basic example ​

ts
import { groupRoutes, createRoute } from 'mobx-route';

const routesGroup = groupRoutes({
  index: createRoute('/', { index: true }),
  fruits: createRoute('/fruits'),
  memes: groupRoutes({
    index: createRoute('/memes', { index: true }),
    list: createRoute('/memes/list'),
    details: createRoute('/memes/:id'),
  }),
});

routesGroup.routes.fruits.open();
routesGroup.isOpened; // true if any child is open
ts
export const admin = groupRoutes({
  index: createRoute('/admin', { index: true }),
  users: createRoute('/admin/users'),
  settings: createRoute('/admin/settings'),
});

admin.routes.users.open(); // prefer opening child routes directly

Methods and properties ​

routes ​

The route collection object passed to the constructor.

isOpened computed ​

true if at least one child route (or its descendants) is open.

ts
admin.routes.users.open();
admin.isOpened; // true

indexRoute computed ​

Default child for group.open(). Resolved in order:

  1. indexRoute passed to groupRoutes(routes, indexRoute) or new RouteGroup(routes, indexRoute)
  2. First child with isIndex (index: true in config)
ts
const explicitIndex = createRoute('/custom-index', { index: true });
const fruits = groupRoutes(
  { list: createRoute('/fruits'), details: createRoute('/fruits/:id') },
  explicitIndex,
);
fruits.indexRoute === explicitIndex; // true

canNavigate computed ​

true if open() has a target β€” either an own indexRoute or a nested RouteGroup that itself can navigate. Useful to render group entry points conditionally (e.g. hide a sidebar section when it has nowhere to go).

ts
const empty = groupRoutes({ foo: createRoute('/foo') });
empty.canNavigate; // false

const withIndex = groupRoutes({
  index: createRoute('/dashboard', { index: true }),
});
withIndex.canNavigate; // true

open(...args) ​

Opens the group's indexRoute. Use it for "go to this section's default page"; call group.routes.<child>.open() for everything else.

ts
export const projects = groupRoutes({
  list: createRoute('/projects', { index: true }),
  new: createRoute('/projects/new'),
  details: createRoute('/projects/:id'),
});

projects.open(); // β†’ /projects (opens `list`)

projects.routes.new.open();
projects.routes.details.open({ id: 42 });

Ways to define the index:

  • { index: true } on a child route
  • second argument: groupRoutes({ ... }, explicitIndexRoute)

group.open() is not a general-purpose navigate() helper β€” export the group and call group.routes.<child>.open() at call sites.

Without any navigable target (canNavigate === false), open() does nothing β€” Warning #1.

Nested groups ​

If the parent has no index, open() walks child keys in declaration order and delegates to the first nested RouteGroup that can navigate (canNavigate === true). Non-group children and groups with no reachable index are skipped.

ts
export const app = groupRoutes({
  shop: groupRoutes({ index: createRoute('/shop', { index: true }) }),
  admin: groupRoutes({ index: createRoute('/admin', { index: true }) }),
});

app.open();
// 1. `app` has no index β†’ walk children in order
// 2. first key is `shop` β†’ it's a group with an index β†’ delegate
// 3. shop.open() β†’ shop's index β†’ /shop

A group with no index of its own is skipped, the search continues to the next sibling:

ts
export const app = groupRoutes({
  noindex: groupRoutes({
    foo: createRoute('/foo'),
    bar: createRoute('/bar'),
  }),
  dashboard: groupRoutes({
    index: createRoute('/dashboard', { index: true }),
  }),
});

app.open();
// `noindex` cannot navigate β†’ skipped
// `dashboard` can β†’ delegate β†’ /dashboard

If you do not want to rely on declaration order at all, pass the index explicitly: groupRoutes(routes, myIndexRoute).

When it helps ​

  • Logical app sections (admin, shop, settings)
  • Passing a subtree to a layout or guard
  • section.open() only for β€œgo to this section’s home” β€” not instead of section.routes.page.open()

Groups organize routes; they do not create a separate history β€” that stays in routeConfig.

Released under the MIT License.