Wondering what’s next for npm?Check out our public roadmap! »

    trace-router
    TypeScript icon, indicating that this package has built-in type declarations

    0.10.0 • Public • Published

    NPM Version NPM Downloads GitHub issues

    Trace Router

    The next generation router for your app

    Installation

    yarn add effector trace-router
    

    Examples

    Create a router:

    import history from 'history/browser';
    import { createRouter, history } from 'trace-router';
     
    export const router = createRouter({ history });

    Create routes:

    // This route is used only for redirection below
    export const exactRoot = router.add({ path: '/' });
     
    // User section
    export const user = router.add('/user(/.*)?'); // parent route
    export const userProfile = router.add('/user');
    export const userTickets = router.add('/user/tickets');
    export const userTicket = router.add<{ id: number }>('/user/tickets/:id');
     
    // Info section
    export const joinUs = router.add('/join-us');
    export const about = router.add('/about');
    export const privacy = router.add('/privacy');
     
    // Merge routes to create a parent route
    // When you can't create common path
    export const info = router.merge([joinUs, about, privacy]);
     
    // Redirect from "/" to "/user"
    exactRoot.visible.watch(visible => {
      if (visible) {
        user.redirect();
      }
    });

    Use routes in React (trace-router-react package):

    export const Root = () => (
      <>
        {useRoute(user) && <UserPage />}
        {useRoute(info) && <InfoPage />}
        {useStore(router.noMatches) && <NotFound />}
      </>
    );
     
    export const UserPage = () => (
      <AppFrame>
        <UserTemplate>
          {useRoute(userProfile) && <UserProfile />}
          {useRoute(userTickets) && <UserTickets />}
          {useRoute(userTicket) && <UserTicket />}
        </UserTemplate>
      </AppFrame>
    );
     
    export const InfoPage = () => (
      <AppFrame>
        <InfoTemplate>
          {useRoute(joinUs) && <JoinUs />}
          {useRoute(about) && <About />}
          {useRoute(privacy) && <Privacy />}
        </InfoTemplate>
      </AppFrame>
    );

    You can also use Route component instead of a hook:

    <Route of={map} component={MapPage} />

    Use links to navigate routes directly:

    <Link to={about}>About</Link>

    Use can add params to the route (if it has ones):

    <Link to={userTicket} params={{ id: 100 }}>
      Month
    </Link>

    The above link compiles to something like:

    <a href="/user-tiket/100" onClick={/* prevent default & navigate */}>
      Join Us
    </a>

    Here is how you compile route to a string:

    const href = route.compile({
      params: { id: 100 },
      query: {
        lang: 'ru',
      },
      hash: '#description',
    });

    Manual route navigation:

    <Button onClick={() => product.navigate({ id: '100' })} />

    or redirect + compile as an example:

    <Button
      onClick={() =>
        product.router.redirect({
          to: product.compile({ params: { id: '100' } }),
          state: { back },
        })
      }
    />

    You can use another history for a router:

    import hashHistory from 'history/hash';
    import { router } from '~/core/router';
     
    router.use(hashHistory);

    You can bind one router to another:

    export const product = router
      .add<{ tab: string }>('/product:tab(.*)?')
      .bind('tab', { router: tabRouter });

    .bind method binds child router path to a parent router parameter

    You can have an url /product/info where: /product - the path of the main router (without a parameter) /info - tabRouter path

    Types

    Router
    export type Router<Q extends Query = Query, S extends State = State> = {
      history: History<S>;
      historyUpdated: Event<Update<S>>;
      historyUpdate: Store<Update<S>>;
      navigate: Event<ToLocation<S>>;
      redirect: Event<ToLocation<S>>;
      shift: Event<Delta>;
      back: Event<void>;
      forward: Event<void>;
      location: Store<Location<S>>;
      action: Store<Action>;
      pathname: Store<Pathname>;
      search: Store<Search>;
      hash: Store<Hash>;
      state: Store<S>;
      key: Store<Key>;
      href: Store<Href>;
      query: Store<Q>;
      hasMatches: Store<boolean>;
      noMatches: Store<boolean>;
      add: <P extends Params = Params>(
        pathConfigPattern | RouteConfig
      ) => Route<P, Router<Q, S>>;
      merge: <T extends Route[]>(routes: T) => MergedRoute;
      none: <T extends Route[]>(routes: T) => MergedRoute;
      use: (
        givenHistoryBrowserHistory<S> | HashHistory<S> | MemoryHistory<S>
      ) => void;
    };
    Route
    export type Route<P extends Params = Params, R = Router> = {
      visible: Store<boolean>;
      params: Store<null | P>;
      config: RouteConfig;
      compile: (compileConfig?: CompileConfig<P>) => string;
      router: R extends Router<infer Q, infer S> ? Router<Q, S> : never;
      navigate: Event<P | void>;
      redirect: Event<P | void>;
      bindings: Partial<{ [K in keyof P]: BindConfig }>;
      bind: (
        paramkeyof P,
        bindConfig{
          router: Router;
          parse?: (rawParam?: string) => string | undefined;
          format?: (path?: string) => string | undefined;
        }
      ) => Route<P, R>;
    };
    Other typings
    export type ToLocation<S extends State = State> = 
      | string
      | { to?: To; state?: S };
    export type Delta = number;
    export type Href = string;
    export type Pattern = string;
    export interface Query extends ObjectString {}
    export interface Params extends ObjectUnknown {}
     
    export type RouterConfig<S extends State = State> = {
      history?: BrowserHistory<S> | HashHistory<S> | MemoryHistory<S>;
      root?: InitialEntry;
    };
     
    export type RouteConfig = {
      path: Pattern;
      matchOptions?: ParseOptions & TokensToRegexpOptions & RegexpToFunctionOptions;
    };
     
    export type CompileConfig<P extends Params = Params> = {
      params?: P;
      query?: string[][] | Record<string, string> | string | URLSearchParams;
      hash?: string;
      options?: ParseOptions & TokensToFunctionOptions;
    };
     
    export type BindConfig = {
      router: Router;
      parse?: (rawParam?: string) => string | undefined;
      format?: (path?: string) => string | undefined;
    };
     
    export type MergedRoute = {
      visible: Store<boolean>;
      routes: Route[];
      configs: RouteConfig[];
    };

    Repo

    Give trace-router a star!

    GitHub ★: https://github.com/doasync/trace-router

    Install

    npm i trace-router

    DownloadsWeekly Downloads

    39

    Version

    0.10.0

    License

    MIT

    Unpacked Size

    128 kB

    Total Files

    24

    Last publish

    Collaborators

    • avatar