Navigation

After routes are defined, Retend’s navigation APIs change routes without a full browser reload.

<Link> provides declarative navigation. It renders an HTML <a> element and intercepts clicks to update the URL and rendered route.

Because it uses an <a> element, it retains browser link behavior, including accessibility semantics, search engine discoverability, and opening links in a new tab.

import { Link } from 'retend/router';

export function NavigationMenu() {
  return (
    <nav class="main-nav">
      <Link href="/">Home</Link>
      <Link href="/about">About Us</Link>
      <Link href="/contact">Contact</Link>
    </nav>
  );
}

Standard HTML attributes like class, id, or aria-label can be passed directly to the <Link> component:

<Link
  href="/signup"
  class="btn btn-primary"
  aria-label="Sign up for an account"
>
  Get Started
</Link>

Replacing History

By default, clicking a <Link> adds an entry to browser history, so the Back action returns to the previous route.

The replace prop replaces the current history entry. This can prevent the previous route, such as a login page after authentication, from being restored by Back:

<Link href="/dashboard" replace>
  Go to Dashboard
</Link>

Programmatic navigation is used when an operation, such as form submission or payment completion, is meant to change the route.

useRouter() provides access to the router, and router.navigate() changes the route.

import { useRouter } from 'retend/router';
import { Cell } from 'retend';

export function LoginForm() {
  const router = useRouter();

  const loginTask = Cell.task(async () => {
    await performLogin();
    await router.navigate('/dashboard');
  });

  const handleSubmit = () => {
    loginTask.runWith(undefined);
  };

  return (
    <form onSubmit--prevent={handleSubmit}>
      {/* ... form fields ... */}
      <button type="submit" disabled={loginTask.pending}>
        Log In
      </button>
    </form>
  );
}

router.replace('/login') replaces the current browser history entry instead of adding one.

Both router.navigate() and router.replace() return Promises. They are awaited when code needs to run after the route transition completes.