Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: static operator for defining groups of routes #1

Open
AlexandrHoroshih opened this issue Feb 15, 2022 · 4 comments
Open

RFC: static operator for defining groups of routes #1

AlexandrHoroshih opened this issue Feb 15, 2022 · 4 comments
Labels
RFC Proposal requires more discussion

Comments

@AlexandrHoroshih
Copy link

AlexandrHoroshih commented Feb 15, 2022

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

@AlexandrHoroshih
Copy link
Author

Also, declarative api like this one, can probably more or less easily used with other UI-frameworks 🤔

@sergeysova
Copy link
Member

sergeysova commented Feb 15, 2022

I propose to name method like createRoutesView. Because routes as is can conflict with routes variable in the user specific source code.

Ex.: on the readme.md we have an example:

import { HomePage } from './routes'

const router = createHistoryRouter({ routes });

If method would have name routes, it will force user to rename their variable to something another, may be not semantic.

Why routesView is in the name?

Because method maps route to a view. We are not just createRoutes, we are creating mapping between all passed routes and correspond views

@sergeysova sergeysova added the RFC Proposal requires more discussion label Feb 15, 2022
@AlexandrHoroshih
Copy link
Author

AlexandrHoroshih commented Feb 15, 2022

🤔 createRoutesView is still kind of long name for this case

Maybe it could be just routesView? Or even just views({ ... })

@sergeysova
Copy link
Member

sergeysova commented Feb 17, 2022

I don't like short names, because they are don't describe what really they are doing.
views what?
routesView who are viewing routes? Or it is "routes are viewing"?

I think it is better to name operators/methods as a verb. With createRoutesWith we have friendly name like createStore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RFC Proposal requires more discussion
Projects
None yet
Development

No branches or pull requests

2 participants