Skip to content
On this page

Page Layout

Most applications have a layout structure resembling something like the following:

  • Header
  • Page Content (dynamic based on route)
  • Footer

Type Route is flexible enough to let the above pattern be accomplished in a variety of ways. While flexibility is powerful it also helps to have some guidance when figuring out your approach.

Bad Example
tsx
import React, { useState, useEffect } from "react";
import { createRouter, defineRoute } from "type-route";

const { routes, useRoute } = createRouter({
  home: defineRoute("/"),
  foo: defineRoute("/foo"),
  bar: defineRoute("/bar"),
});

function App() {
  const route = useRoute();

  return (
    <>
      {route.name === "home" && <HomePage />}
      {route.name === "foo" && <FooPage />}
      {route.name === "bar" && <BarPage />}
      {route.name === false && <NotFoundPage />}
    </>
  );
}

function Header() {
  return (
    <nav>
      <a {...routes.home().link}>Home</a>
      <a {...routes.foo().link}>Foo</a>
      <a {...routes.bar().link}>Bar</a>
    </nav>
  );
}

function Footer() {
  return (
    <footer>
      <div>Footer</div>
    </footer>
  );
}

function HomePage() {
  return (
    <>
      <Header />
      <div>Home Page</div>
      <Footer />
    </>
  );
}

function FooPage() {
  return (
    <>
      <Header />
      <div>Foo Page</div>
      <Footer />
    </>
  );
}

function BarPage() {
  return (
    <>
      <Header />
      <div>Bar Page</div>
      <Footer />
    </>
  );
}

function NotFoundPage() {
  return (
    <>
      <Header />
      <div>Bar Page</div>
      <Footer />
    </>
  );
}

The above example would work but, on every page change, the Header and Footer components would be unmounted and remounted unnecessarily. Consider the following approach instead:

Good Example
tsx
import React, { useState, useEffect } from "react";
import { createRouter, defineRoute } from "type-route";

const { routes, useRoute } = createRouter({
  home: defineRoute("/"),
  foo: defineRoute("/foo"),
  bar: defineRoute("/bar"),
});

function App() {
  const route = useRoute();

  return (
    <>
      <Header />
      {route.name === "home" && <HomePage />}
      {route.name === "foo" && <FooPage />}
      {route.name === "bar" && <BarPage />}
      {route.name === false && <NotFoundPage />}
      <Footer />
    </>
  );
}

function Header() {
  return (
    <nav>
      <a {...routes.home().link}>Home</a>
      <a {...routes.foo().link}>Foo</a>
      <a {...routes.bar().link}>Bar</a>
    </nav>
  );
}

function Footer() {
  return (
    <footer>
      <div>Footer</div>
    </footer>
  );
}

function HomePage() {
  return <div>Home Page</div>;
}

function FooPage() {
  return <div>Foo Page</div>;
}

function BarPage() {
  return <div>Bar Page</div>;
}

function NotFoundPage() {
  return <div>Bar Page</div>;
}

This good example ensures that the Header and Footer components are not unmounted then remounted unnecessarily.

Type Route is a Zilch project