Phoenix LiveView: When to use navigate, patch, href, redirect, push_patch, push_navigate
Tags: phoenix, elixir, liveview
Published: 2023-10-18 11:47:59

## TL;DR

- `navigate` and `push_navigate`: When you're navigating to the same `live_session`.
- `patch` and `push_patch`: When you're navigating to the same module/page/liveview. For example, when only the attributes change - from `/posts/1` to `/posts/2`.
- `href` and `redirect`: When you're navigating to another live session or outside a live view.
- Don't use `navigate` when navigating to another `live_session`.

## Examples

Let's say we have the following routes:

```elixir
live_session :public_routes do
  live "/", HomeLive
  live "/posts", PostsLive
end

live_session :private_routes do
  live "/posts/:id/content, PostEdit, :content
  live "/posts/:id/metadata, PostEdit, :metadata
end
```

We have two live sessions: `public_routes` and `private_routes`.

### From / to /posts

In this case, we'll use `navigate` (client) or `push_navigate` (server) because we're navigating to the same `public_routes` live session:

```elixir
<.link navigate={~p"/posts"}>Posts</.link>
```

This will keep the browser page but mount a new LiveView process to reload its content only.

### From /posts to /posts/:id/content

In this case, we'll use `href` (client) or `redirect` (server) because we're moving from the `public_routes` live session to the `private_routes` one:

```elixir
<.link href={~p"/posts/#{post.id}/content"}>Edit</.link>
```

This will cause a full page reload.

### From /posts/:id/content to /posts/:id/metadata

In this case, we'll use `patch` (client) or `push_patch` (server) because we're navigating to the same page/module. We're only changing the page attributes:

```elixir
<.link patch={~p"/posts/:id/metadata"}>Metadata</.link>
```

When using `patch` you'll also need to define a [`handle_params` callback](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#c:handle_params/3) to handle the parameters change.

While `navigate` mounts a new live view, `patch` updates the current live view, sending less data back.

## Motivation

I recently [made a mistake](https://github.com/phoenixframework/phoenix_live_view/issues/2861) where the topbar would be displayed twice while navigating between different live sessions. [This happens because I tried to](https://github.com/phoenixframework/phoenix_live_view/issues/2861#issuecomment-1767049732):

> live navigate (<.link navigate) across live sessions, which requires an extra round trip to the server and looks like the cause of your unwanted behavior. Regular link href is all you need here and it will not dispatch the loading event in that case, resolving the behavior you're seeing.

Reading the [docs](https://hexdocs.pm/phoenix_live_view/welcome.html), it was confusing to me to understand the difference between all those options, especially because I was looking at the wrong places.

I was looking the [push_navigate/2](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_navigate/2) and [push_patch/2](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#push_patch/2) docs but a better explanation is available on the [live navigation](https://hexdocs.pm/phoenix_live_view/live-navigation.html) and [link attributes](https://hexdocs.pm/phoenix_live_view/Phoenix.Component.html#link/1-attributes) docs.