Skip to main content

Route and Components

This section describes routes and components relations.

Page structure

For all application routes, you can specify the list of components names that will be rendered on this route. This list can contain only components keys, whereas according React components will be automatically resolved from special service - ComponentRegistry.

List of possible components:

Page structure with all components looks like this, simplified:

const Root = () => (
<LayoutComponent>
<Header />
<NestedLayoutComponent>
<ErrorBoundaryComponent>
<PageComponent />
</ErrorBoundaryComponent>
</NestedLayoutComponent>
<Footer />
</LayoutComponent>
);

File-System Routing

For FS routes, route with list of components will be created automatically, and all components will be automatically registered in ComponentRegistry.

For example, from this file structure:

src
└── routes
├── index.tsx
├── _layout.tsx
└── _error.tsx

This route will be created:

[{
path: '/',
config: {
pageComponent: '@/routes/index',
nestedLayoutComponent: '@/routes/index__layout',
errorBoundaryComponent: '@/routes/index__errorBoundary',
},
}];

Manually created routes

For manually created routes, you need to use pages directory, all components from this directory will be automatically registered in ComponentRegistry.

Example file structure:

src
└── pages
├── main.tsx
├── main-layout.tsx
└── main-error.tsx

And you can create this route with all of this components:

import { SpaRouterModule } from '@tramvai/modules-router';

createApp({
modules: [
SpaRouterModule.forRoot([{
name: 'main',
path: '/',
config: {
pageComponent: '@/pages/main',
nestedLayoutComponent: '@/pages/main-layout',
errorBoundaryComponent: '@/pages/main-error',
},
}]),
],
});

Default components

For all components can be specified default component, e.g. that keys will be used if component with specified in route config key is not found in ComponentRegistry:

const mapping = {
pageComponent: 'pageDefault',
nestedLayoutComponent: 'nestedLayoutDefault',
errorBoundaryComponent: 'errorBoundaryDefault',
layoutComponent: 'layoutDefault',
}

Default Root Layout already provided by token DEFAULT_LAYOUT_COMPONENT, this is default application layout and it is not recommended to change it.

Default Page Error Boundary can be provided by token DEFAULT_ERROR_BOUNDARY_COMPONENT.

Default Page Nested Layout is not supported for FS routes or pages and is not necessary, because Root LAYOUT_OPTIONS is more powerful mechanism - wrappers.page is complete alternative for nested layout in page components hierarchy.

Default Page Component is not supported for FS routes or pages, only for legacy bundles.

Bundles (legacy)

caution

Bundles is legacy feature, and it is recommended to use File-System routing in new projects.

For bundles situation is more complicated, because bundles can group several components, and different routes can use the same bundle. Also, it means that for bundles additional level of default components will be used.

Important default for routes if bundles is used, is default bundle and page component keys:

const routeConfig = {
bundle: 'mainDefault',
pageComponent: 'pageDefault',
};

It means that all routes without FS routing will use mainDefault bundle, and get pageDefault page component from this bundle. Example of this default bundle:

bundles/mainDefault.ts
import { createBundle } from '@tramvai/core';
import { lazy } from '@tramvai/react';

export const mainDefault = createBundle({
name: 'mainDefault',
components: {
pageDefault: lazy(() => import('../components/main-page')),
},
});

And for this simple route, components/main-page.tsx page component will be rendered:

import { SpaRouterModule } from '@tramvai/modules-router';

createApp({
modules: [
SpaRouterModule.forRoot([{
name: 'main',
path: '/',
}]),
],
bundles: {
mainDefault: () => import(/* webpackChunkName: "mainDefault" */ './bundles/mainDefault'),
},
});

All other default components will applied to route with this bundle, e.g.:

bundles/mainDefault.ts
import { createBundle } from '@tramvai/core';
import { lazy } from '@tramvai/react';

export const mainDefault = createBundle({
name: 'mainDefault',
components: {
pageDefault: lazy(() => import('../components/main-page')),
nestedLayoutDefault: lazy(() => import('../components/main-layout')),
errorBoundaryDefault: lazy(() => import('../components/main-error')),
layoutDefault: lazy(() => import('../components/layout')),
},
});

Defaults from Defaults components section also will be applied, but with lower priority.

In summary:

  • If pageComponent, layoutComponent, nestedLayoutComponent or errorBoundaryComponent properties is specified in route config, they values will be used as components keys
  • Otherwise, pageDefault, layoutDefault, nestedLayoutDefault or errorBoundaryDefault will be used as components keys
  • Then, if current bundle components has component with this key, it will be used
  • Otherwise, tramvai will try to find this keys in default components
  • Only for Page Component, if it is not found anywhere, 500 error will be thrown