Description
I suggest to add an static operator (like @effector/reflect) to define groups of routes and their veiws
I think, that declarative static config it is better for a few reasons:
- It is allows library to perform some optimizations, that are impossible inside dynamic contexts like React. Also it allows library developer to introduce new features in a safer way
- It does not push end user to perform manual control-flow inside react render - it is easier to understand and debug static configuration, rather than bunch of ternary operators
It may look something like that
(it is just an RFC of the API, with some of the cases, i think, api like that may cover)
Base api
Operator, which takes a list of routes and views and returns React component, which renders specific view based on which route can be matched
const Routes = routes({
config: [
{
view: LoginPage,
route: loginPage,
},
{
view: HomePage,
route: homePage,
},
// ...
],
})
This operator must be called statically - not inside reactive context like React itself
Defaults
Once rendered, component must decide which route to render - but if there is no matched routes, something still may be rendered:
const Routes = routes({
config: [
{
view: LoginPage,
route: loginPage,
},
// ...
],
// default component, if no routes matched
default: NotFoundPage,
// `() => null` as default, if no component provided
});
Also it may be not the render, but some action instead 🤔
const Routes = routes({
config: [
{
view: HomePage,
route: homePageRoute,
},
//...
],
// default action config
default: {
redirect: landingPageRoute,
},
});
Additional configuration
I think, that static definition allows to setup additional configuration for every route, something like that
const Routes = routes({
config: [
{
view: HomePage,
route: homePage,
visible: $userAuthtorized,
},
],
});
Also, i think, route groups may have config themselves 🤔
const Routes = routes({
visible: $userAuthtorized,
config: [
// ...
{
view: HomePage,
route: homePage,
},
// ...
],
});
Nested routes
I think, route groups can be nested in each other - this way it becomes easier to create subroutes
const MainRoutes = routes({
config: [
{
route: mainRoute,
view: routes({
visible: $authtorized,
config: [
{
route: mainRouteFirstSubPage,
view: SubPage,
},
// ...
],
default: {
redirect: mainRouteFirstSubPage,
},
}),
},
{
route: loginPage,
view: LoginPage,
},
],
});
Since decision about which route to render still happens at react in runtime, nesting can be done this way too:
<InsideHomePageRoute>
<TabsWrapper>
// nested routes group
<HomePageTabsRoutes />
</TabsWrapper>
</InsideHomePageRoute>
But since all configuration can be done via declarative config of routes
, there is no need to do some tricky control flow in react and still support hardcore cases, like nested tabs inside other nested tabs and so on - runtime part just have to check, which of its routes list currently matches first