0.3.0 • Published 12 months ago

@tigerlegab/react-router v0.3.0

Weekly downloads
-
License
MIT
Repository
github
Last release
12 months ago

react-router · GitHub license Published on NPM Minified size Tree-shakeable

Simple router for react with data loader.

Example

// Dashboard.tsx
export default function Dashboard() {
   return <>Dashboard</>;
}

// Item.tsx
export loader(params: { id: string; }) {
   return fetch("/api/item" + params.id);
}

export default function Item(props : { params: { id: string; }; data: any; }) {
   return (
      <>
         id: {props.params.id}
         data: {JSON.stringify(props.data)}
      </>
   );
}

// Layout.tsx
import { Router, BrowserRoute } from "@tigerlegab/react-router";
import { Loader } from "./Loader";

const Page404 = lazyLoad(() => import("./Page404"));
const Page500 = lazyLoad(() => import("./Page500"));
const routes: BrowserRoute[] = [
   {
      path: "/",
      element: () => import("./Dashboard"),
   },
   {
      path: "/:userId",
      element: () => import("./User"),
   }
];

export default function Layout() {
   return (
      <>
         <header>
            <Link to="/">Dashboard</Link>
            <Link to="/item/0001">Item One</Link>
         </header>

         <main>
           <Router
               routes={routes}
               page404={<Page404 />}
               page500={(error) => <Page500 error={error} />}
               pageLoader={{ element: <Loader />, firstLoadOnly: true }}
            />
         </main>
      </>
   );
}

During navigation, it will first look for the matching route, then import the file, then call the data loader function and waits for the response before displaying the content. You can use useNavigationStatus() to handle loading state. For example a loading bar:

export function LoadingBar() {
  const status = useNavigationStatus();
  const [progress, setProgress] = useState(0);

   useEffect(() => {
      if (status === "loaded") {
         setProgress(100);
         window.setTimeout(() => setProgress(0), 160);
      }
      else {
         setProgress(randomInt(18, 20));
         const tick = () => setProgress(curr => curr + 1);
         const id = window.setInterval(tick, 500);
         return () => window.clearInterval(id);
      }
   }, [status]);

   return (
      <Progress
         size="xs"
         radius={0}
         value={progress}
         classNames={classes}
         data-mounted={progress > 0}
      />
   );
}

function randomInt(min: number, max: number): number {
  return Math.floor(Math.random() * (max - min + 1) + min)
}

Components

  • Router

Props

interface RouterProps {
   /**
    * @required
    * List of routes
    */
   routes: BrowserRoute[];
   /**
    * @required
    * Default display if theres no matching route
    */
   page404: React.ReactNode;
   /**
    * @optional
    * Default display if loader returns an error
    */
   page500: page500: (error: string) => React.ReactNode;
   /**
    * @optional
    * Default display if location status is in pending state
    */
   pageLoader?: {
      // Element of the pageLoader.
      element: React.ReactNode;
      // Option to show pageLoader at first load only.
      firstLoadOnly?: boolean;
   };
}

interface BrowserRoute {
   /**
    * @required
    * The path to match for this route
    */
   path: string;
   /**
    * @required
    * The element to display for this route
    */
   element: (() => Promise<{
      default: (props?: any) => React.JSX.Element;
      loader?: (params?: any) => Promise<any>;
   }>) | React.ReactNode;
}

Hooks

  • useBrowserLocation - Listens to location changes and returns the current location data.
  • useNavigationStatus - Listens to location status changes and returns the current location status. Statuses are pending and loaded.

Utils

Functions that can also be used outside of react.

  • navigate - Navigates to a new browser location.
  • getBrowserLocation - Returns the current location data.
  • parseRoute - Check if the route matches current pathname and returns the route value. Uses regexparam.

Location data

interface BrowserLocation {
   path: string;
   state?: any;
   search?: {
      [x: string]: any;
   };
}

Navigation options

interface NavigateOptions {
   /**
    * Set to `true` to use `window.history.replace`
    */
   replace?: boolean;
   /**
    * The value for `window.history.state`
    */
   state?: boolean | any;
}

parseRoute usage

parseRoute("/item", "/item")
//=> {}

parseRoute("/item/:id", "/item")
//=> undefined

parseRoute("/item/:id?", "/item")
//=> { id: null }

parseRoute("/item/:id?", "/item/0001")
//=> { id: "0001" }

See regexparam usage for more info.

Developement issue

  1. Hot reload not working in development. You may need to refresh the browser to view the updates.
0.3.0

12 months ago

0.2.2

12 months ago

0.2.1

1 year ago

0.2.0

1 year ago

0.1.4

1 year ago

0.1.3

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago