# Client-side navigation

After the server has rendered the initial page, the client takes over and handles all subsequent navigation. This can be done by using the client components exported by the `@lazarv/react-server/navigation` module or by the functions exposed by the `useClient` hook from the `@lazarv/react-server/client` module. You can use these functions to navigate to a new page, prefetch a page, or refresh the current page.

It's recommended to use the built-in client components for navigation and refresh. These components will automatically start a React transition to render only the parts of the page that are changing. This will improve the user experience by reducing the amount of time the user has to wait for the page to load.

Functions exposed by the `useClient` hook are more low-level and should be used only when you need to start a React transition manually.

## Link

You can navigate to a new page by using the `Link` client component exported by the `@lazarv/react-server/navigation` module.

```jsx
import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about">About</Link>
    </div>
  );
}
```

### Prefetch

You can enable prefetching of the page by passing the `prefetch` prop to the `Link` component. This will prefetch the page when the user hovers over the link.

```jsx
import { Link } from "@lazarv/react-server/client";

export default function Home() {
  return (
    <div>
      <Link to="/about" prefetch>
        About
      </Link>
    </div>
  );
}
```

By default, the prefetched page will be cached indefinitely. You can change this behavior by passing the timeout value in the `prefetch` prop to the `Link` component. The `prefetch` prop accepts a number which represents the number of milliseconds the page will be cached for. After the timeout expires, the page will be removed from the cache and the next time the user hover over the link, the page will be prefetched again.

```jsx
import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about" prefetch={5000}>
        About
      </Link>
    </div>
  );
}
```

To programmatically prefetch a page you can use the `prefetch` function returned by the `useClient` hook.

```jsx
import { useClient } from "@lazarv/react-server/client";

export default function Home() {
  const { prefetch } = useClient();

  return (
    <div>
      <button onMouseOver={() => prefetch("/about")}>About</button>
    </div>
  );
}
```

### Rollback

When the user navigates away from a page the router will cache the last page when you specify a `rollback` prop on the `Link` component. This will allow the user to navigate back to the previous page without having to wait for the server to render the page again. The provided value represents the number of milliseconds the page will be cached for. After the timeout expires, the page will be removed from the cache and the next time the user navigates back to the page, the page will be rendered again by the server.

```jsx
import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about" rollback={5000}>
        About
      </Link>
    </div>
  );
}
```

## Navigate

To programmatically navigate to a new page you can use the `navigate` function returned by the `useClient` hook. It's recommended to use `navigate` in a React transition to render only the parts of the page that are changing.

```jsx
import { startTransition } from "react";
import { useClient } from "@lazarv/react-server/client";

export default function Home() {
  const { navigate } = useClient();

  return (
    <div>
      <button onClick={() => startTransition(async () => navigate("/about"))}>
        About
      </button>
    </div>
  );
}
```

## Refresh

You can refresh the current page by using the `` client component exported by the `@lazarv/react-server/navigation` module or the `refresh` function returned by the `useClient` hook from the `@lazarv/react-server/client` module.

```jsx
import { Refresh } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Refresh>Click to refresh!</Refresh>
    </div>
  );
}
```

To programmatically refresh the current page you can use the `refresh` function returned by the `useClient` hook. Again, it's recommended to start a React transition for the page refresh.

```jsx
import { startTransition } from "react";
import { useClient } from "@lazarv/react-server/client";

export default function Home() {
  const { refresh } = useClient();

  return (
    <div>
      <button onClick={() => startTransition(async () => refresh())}>
        Refresh
      </button>
    </div>
  );
}
```

## Form

You can navigate to a new page by using the `Form` client component exported by the `@lazarv/react-server/navigation` module. This component will navigate to the current route on form submit using form data as the query parameters.

```jsx
import { Form } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <Form>
      <input name="name" />
      <button type="submit">Submit</button>
    </Form>
  );
}
```

## Outlet

You can use the `ReactServerComponent` to create an outlet which you can use for sub-page navigation. It's a modern React Server Component driven version of the `` element. When using a `Link` or `Refresh` component or programmatically navigating with the `navigate` or `replace` functions, the client-side router will automatically update the content of the outlet by rendering the result of server-side rendering the outlet. You need to handle the server-side rendering of the outlet yourself using server-side routing and using the [useOutlet](/features/http#outlet) helper function.

```jsx
"use client";

import { Link, ReactServerComponent } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/photos/1" target="modal">My photo</Link>
      <ReactServerComponent outlet="modal" />
    </div>
  );
}
```

There's four types of `Link` or `Refresh` navigation inside a `ReactServerComponent`. Unspecified, `target`, `local` and `root`. When using `target` on the `Link` or `Refresh` component, the navigation will only update the content of the outlet with the same name. When using `local`, the navigation will update the content of the parent outlet while URL of the current page is not updated this way. When using `root`, the navigation will update the content of the page. When using an unspecified behavior, the navigation will update the content of the page for each outlet if there are any outlets on the page.

```jsx
"use client";

import { Link, ReactServerComponent } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <ReactServerComponent outlet="modal">
        <Link to="/photos/2" local>My photo</Link>
      </ReactServerComponent>
    </div>
  );
}
```

When using the `ReactServerComponent` with the `defer` prop, the content of the outlet will be rendered only when the user navigates to the page that contains the `ReactServerComponent` with the `defer` prop. This can be useful when you want to defer the rendering of the content of the outlet until the user navigates to the page that contains the `ReactServerComponent` with the `defer` prop. The content of the outlet will be fetched from the server.

You can also specify the `url` prop on the `ReactServerComponent` to specify the URL of the content of the outlet. This can be useful when you want to render the content of the outlet from a different URL than the current page.

Using both `defer` and `url` props on the `ReactServerComponent` you can achieve a similar behavior to the `iframe` element.

## useClient

The `useClient` hook returns an object with the following properties:

- `navigate(url: string, options: { outlet?: string; push?: boolean; rollback?: number; signal?: AbortSignal; fallback?: React.ReactNode; Component?: React.ReactNode })`: A function that navigates to a new page or the specified outlet. The `rollback` option allows you to cache the current page for a specified amount of time.
- `replace(url: string, options: { outlet?: string; rollback?: number; signal?: AbortSignal; fallback?: React.ReactNode; Component?: React.ReactNode })`: A function that replaces the current page with a new page or the content of the specified outlet. The `rollback` option allows you to cache the current page for a specified amount of time.
- `prefetch(url: string, options: { outlet?: string; ttl?: number; signal?: AbortSignal })`: A function that prefetches a page or the content of the specified outlet. The `ttl` option allows you to cache the page for a specified amount of time.
- `refresh(outlet?: string, options: { signal?: AbortSignal; fallback?: React.ReactNode; Component?: React.ReactNode })`: A function that refreshes the current page or the content of the specified outlet.
- `abort(outlet?: string, reason?: unknown)`: A function that aborts navigation of the specified outlet.
You can use these functions for programmatic navigation.

```jsx
import { startTransition } from "react";

import { useClient } from "@lazarv/react-server/client";

export default function Home() {
  const { navigate, replace, prefetch, refresh } = useClient();

  return (
    <div>
      <button onClick={() => startTransition(async () => navigate("/about"))}>
        About
      </button>
      <button onClick={() => startTransition(async () => replace("/about"))}>
        Replace
      </button>
      <button onMouseOver={() => prefetch("/about")}>Prefetch</button>
      <button onClick={() => startTransition(async () => refresh())}>
        Refresh
      </button>
    </div>
  );
}
```

## useOutlet

The `useOutlet` hook returns a set of functions to interact with the current outlet. These functions are the same as the ones returned by the `useClient` hook, but you don't need to specify the `outlet` option. In the example below, the `navigate` function is scoped to the current outlet, not the entire page. But if the current outlet is the root outlet, the `navigate` function will navigate to the entire page.

```jsx
"use client";

import { useOutlet } from "@lazarv/react-server/client";

export default function Home() {
  const { navigate } = useOutlet();

  return (
    <div>
      <button onClick={() => navigate("/about")}>About</button>
    </div>
  );
}
```

## Fallback

The `fallback` option on the `Link` and `Refresh` components allows you to specify a fallback component to render until the outlet starts to render the React Server Component. This can be useful when you want to render a loading indicator or a skeleton while the React Server Component is being rendered immediately, without waiting for the React Server Component request to reach the server.

```jsx
import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about" target="content" fallback={<div>Loading...</div>}>About</Link>
    </div>
  );
}
```

You can also specify the `fallback` option when navigating programmatically with the `navigate` or `replace` functions.

```jsx
import { useClient } from "@lazarv/react-server/client";

export default function Home() {
  const { navigate } = useClient();

  return (
    <div>
      <button onClick={() => navigate("/about", { fallback: <div>Loading...</div> })}>About</button>
    </div>
  );
}
```

## Component

The `Component` option on the `Link` and `Refresh` components allows you to specify a React component to render. This can be useful when you want to render a React component directly in the outlet instead of making a request to the server.

```jsx
import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about" target="content" Component={<div>About</div>}>About</Link>
    </div>
  );
}
```

You can also specify the `Component` option when navigating programmatically with the `navigate` or `replace` functions.

```jsx
import { useClient } from "@lazarv/react-server/client";

export default function Home() {
  const { navigate } = useClient();

  return (
    <div>
      <button onClick={() => navigate("/about", { Component: <div>About</div> })}>About</button>
    </div>
  );
}
```

## Using revalidate

You can use the `revalidate` prop on the `Link`, `Refresh` and `Form` components to control client-side caching of the page or content of the specified outlet. The `revalidate` prop can accept a number which represents the number of milliseconds the page or outlet will be cached for the target URL. After the timeout expires, the page will be removed from the cache and the next time the user navigates to the page, the page will be rendered again by fetching the content from the server rendering the React Server Component.

By default, the `revalidate` prop is not set, which means that the page or outlet will not be cached at all, and every navigation will fetch the content from the server.

```jsx
import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about" revalidate={5000}>About</Link>
    </div>
  );
}
```

You can disable revalidation by passing `false` to the `revalidate` prop. By disabling revalidation, the page or outlet will be cached indefinitely.

```jsx
import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about" revalidate={false}>About</Link>
    </div>
  );
}
```

You can also fully customize the logic for revalidation by passing a function to the `revalidate` prop. The function will receive a context object including the `outlet`, the target `url` and the `timestamp` of the cached content. The function should return a boolean indicating whether the content should be revalidated.

```jsx
"use client";

import { Link } from "@lazarv/react-server/navigation";

export default function Home() {
  return (
    <div>
      <Link to="/about" revalidate={async ({ outlet, url, timestamp }) => {
        return Math.random() > 0.5;
      }}>About</Link>
    </div>
  );
}
```