Browse learning paths

Taskboard 3. Routing

Extend the interactive Taskboard with Tasks and About routes that share the same TaskboardStore.

Table of contents

Stage 3. Add routing

Starting state
Complete Stage 2 so the task list and interactions read one TaskboardStore.
Applied change
Create Tasks and About routes, create the store and Router once in createTaskboardApp, then mount the Router on body.
Observable result
The Tasks and About buttons change screens while the task state remains available through the same store.
Next step
Continue with Stage 4 and load the Tasks screen asynchronously.

Follow the routing flow

Router
new Router() creates the route registry used by Taskboard.
add
router.add(path, handler) registers each path and the view returned when that path matches.
go
router.go(path) resolves the route, renders its view and updates the browser URL after navigation.
catch(404)
router.catch(404, handler) supplies the view used when no route matches.
mountRouter
mountRouter("body", router) mounts the registered router on body so the Tasks and About buttons can switch the rendered route.

src/client-entry.tsx

tsx
import { mountRouter } from "valyrian.js/router";
import { createTaskboardApp } from "./taskboard";

const app = createTaskboardApp();
mountRouter("body", app.router);

src/router.tsx

tsx
import { Router } from "valyrian.js/router";
import { TaskboardApp } from "./app";
import type { TaskboardStore } from "./state";

export function createRouter(store: TaskboardStore) {
  const router = new Router();
  router.add("/", () => (
    <>
      <button onclick={() => router.go("/about")}>About</button>
      <TaskboardApp store={store} />
    </>
  ));
  router.add("/about", () => (
    <main>
      <h1>About Taskboard</h1>
      <button onclick={() => router.go("/")}>Tasks</button>
    </main>
  ));
  router.catch(404, () => <h1>Taskboard page not found</h1>);
  return router;
}

src/taskboard.ts

ts
import { createRouter } from "./router";
import {
  createTaskboardStore,
  type TaskboardState,
} from "./state";

export function createTaskboardApp(
  initialState: Partial<TaskboardState> = {},
) {
  const store = createTaskboardStore(initialState);
  const router = createRouter(store);
  return { store, router };
}