Skip to content
Back to skills

1547 Assigns Streams 96a4a154

ASecurity

| Use Case | Solution | |----------|----------| | Small list (< 100 items) | assigns | | Large list (100+ items) | streams | | Paginated/infinite scroll | streams | | Data not needed after render | temporary_assigns | | Async loading with states | AsyncResult |

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 11, 2026
documentationgo

Works with

  • cli

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1547-assigns-streams_96a4a154 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1547 Assigns Streams 96a4a154?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1547 Assigns Streams 96a4a154
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1547-assigns-streams-96a4a154/badge)](https://www.skillsdirectory.com/skills/tools-only-1547-assigns-streams-96a4a154)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Assigns and Streams

## When to Use Each

| Use Case | Solution |
|----------|----------|
| Small list (< 100 items) | assigns |
| Large list (100+ items) | streams |
| Paginated/infinite scroll | streams |
| Data not needed after render | temporary_assigns |
| Async loading with states | AsyncResult |

## Streams

### Basic Usage

```elixir
def mount(_params, _session, socket) do
  {:ok, stream(socket, :posts, Posts.list_posts())}
end

def handle_event("delete", %{"id" => id}, socket) do
  post = Posts.get_post!(id)
  Posts.delete_post!(post)
  {:noreply, stream_delete(socket, :posts, post)}
end
```

### In Templates

```heex
<div id="posts" phx-update="stream">
  <div :for={{dom_id, post} <- @streams.posts} id={dom_id}>
    <%= post.title %>
    <button phx-click="delete" phx-value-id={post.id}>Delete</button>
  </div>
</div>
```

### Stream Operations

```elixir
# Insert at end (default)
stream_insert(socket, :posts, new_post)

# Insert at beginning
stream_insert(socket, :posts, new_post, at: 0)

# Delete
stream_delete(socket, :posts, post)

# Delete by DOM ID
stream_delete_by_dom_id(socket, :posts, "posts-123")

# Reset entire stream
stream(socket, :posts, new_list, reset: true)
```

## AsyncResult

### assign_async

```elixir
def mount(_params, _session, socket) do
  {:ok,
   socket
   |> assign_async(:user, fn ->
     {:ok, %{user: Accounts.get_user!(1)}}
   end)
   |> assign_async([:posts, :comments], fn ->
     {:ok, %{posts: Posts.list(), comments: Comments.list()}}
   end)}
end
```

### Template Handling

```heex
<%# Using async_result component %>
<.async_result :let={user} assign={@user}>
  <:loading>
    <div class="animate-pulse">Loading...</div>
  </:loading>
  <:failed :let={{:error, reason}}>
    <div class="text-red-500">Failed: <%= reason %></div>
  </:failed>
  <div><%= user.name %></div>
</.async_result>

<%# Manual pattern matching %>
<%= case @user do %>
  <% %AsyncResult{ok?: true, result: user} -> %>
    <%= user.name %>
  <% %AsyncResult{loading: true} -> %>
    Loading...
  <% %AsyncResult{failed: reason} -> %>
    Error: <%= inspect(reason) %>
<% end %>
```

## Temporary Assigns

### For Large Rendered Data

```elixir
def mount(_params, _session, socket) do
  {:ok,
   socket
   |> assign(:messages, load_messages())
   |> assign(:form, to_form(%{})),
   temporary_assigns: [messages: []]}
end
```

**Important**: Temporary assigns are cleared after render. Only use for data that doesn't need to persist in socket state.

## Common Mistakes

### Assigns for Large Lists

```elixir
# BAD - 10k items in assigns
def mount(_, _, socket) do
  {:ok, assign(socket, items: Repo.all(Item))}  # All 10k in memory!
end

# GOOD - stream with pagination
def mount(_, _, socket) do
  {:ok,
   socket
   |> assign(:page, 1)
   |> stream(:items, load_page(1))}
end
```

### Not Handling AsyncResult States

```elixir
# BAD - assumes result exists
<%= @user.result.name %>

# GOOD - handle all states
<%= if @user.ok?, do: @user.result.name, else: "Loading..." %>
```

## Review Questions

1. Are streams used for large or paginated collections?
2. Do AsyncResult templates handle loading and error states?
3. Are temporary_assigns used appropriately (not for needed state)?
4. Is stream DOM properly configured (id, phx-update)?

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.