---
name: Author Blazor Component
slug: author-blazor-component
category: Frontend
description: Author Blazor Component creates or reviews Blazor components (.razor files) with correct architecture for parameters, EventCallback, RenderFragment slots, lifecycle, async patterns, and disposal. Use it when writing new Blazor components that do not involve JavaScript interop, forms, prerendering, or HTTP data fetching.
github: "https://github.com/dotnet/skills/tree/main/plugins/dotnet-blazor/skills/author-component"
language: "C#"
stars: 5165
forks: 384
install: "npx degit https://github.com/dotnet/skills/tree/main/plugins/dotnet-blazor/skills/author-component ~/.claude/skills/author-component"
installs_to: ~/.claude/skills/author-component
source_path: plugins/dotnet-blazor/skills/author-component/SKILL.md
collection_size: 25
category_size: 567
collection_url: "https://dirskills.com/collections/dotnet/skills"
added: 2026-08-16T07:00:30.949Z
last_synced: 2026-08-16T07:00:30.949Z
canonical_url: "https://dirskills.com/skills/author-blazor-component"
---

# Author Blazor Component

Author Blazor Component creates or reviews Blazor components (.razor files) with correct architecture for parameters, EventCallback, RenderFragment slots, lifecycle, async patterns, and disposal. Use it when writing new Blazor components that do not involve JavaScript interop, forms, prerendering, or HTTP data fetching.

**Install:**

```bash
npx degit https://github.com/dotnet/skills/tree/main/plugins/dotnet-blazor/skills/author-component ~/.claude/skills/author-component
```

## README

# Author Blazor Component

## Core Rules

- Data flows **down** via `[Parameter]`. Events flow **up** via `EventCallback<T>` (never `Action`/`Func`).
- Never mutate `[Parameter]` properties. Copy to a private field in `OnParametersSet`.
- Use `[Parameter] public T Prop { get; set; }` — never `required` or `init` (causes BL0007).
- Use `[EditorRequired]` for required parameters.
- Handle all states: loading, empty, loaded, error — each with `@if`/`@else`.
- Use `@key` on repeated elements in loops for efficient diffing.
- Use `IReadOnlyList<T>` (not `IEnumerable<T>`) for collection parameters.

## RenderFragment & Generics

```csharp
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public RenderFragment<TItem>? RowTemplate { get; set; }  // generic template
```

Use `@typeparam TItem` for generic components.

## File Patterns

- **Single-file:** `.razor` with `@code` block when logic < ~50 lines.
- **Code-behind:** `.razor` + `.razor.cs` with `partial class` when logic > ~50 lines.

## Disposal

Implement `IAsyncDisposable` (not `IDisposable`) when the component owns subscriptions, timers, or CTS.
In `DisposeAsync`: unsubscribe (`-=`), cancel CTS, dispose resources. Never call `StateHasChanged`.

## Async Patterns

- `await` every async operation. Never use `.Result`, `.Wait()`, `Task.Run`, `ContinueWith`, `Thread.Start`.
- **Debounce:** `Task.Delay` + `CancellationTokenSource`. Cancel old CTS, create new, await delay, do work. Never use `System.Threading.Timer` or `System.Timers.Timer`.
- **Polling:** Loop in `OnInitializedAsync` with `await Task.Delay(interval, token)` — stays on sync context.
- **External events** (`Action<T>`): Use `async void` handler + `await InvokeAsync(() => { state++; StateHasChanged(); })` + `catch` → `DispatchExceptionAsync`. Never `_ = InvokeAsync(...)`.
- Cancel CTS in `DisposeAsync`. Don't catch `ObjectDisposedException` — use CTS cancellation.

## Don'ts

- `required`/`init` on `[Parameter]` — runtime failure
- Mutate `[Parameter]` — copy to private field in `OnParametersSet`
- `Action`/`Func` for events — use `EventCallback<T>`
- `Task.Run`/`.Result`/`.Wait()`/Timer for debounce — deadlock or thread-pool escape
- Inline `style` attributes — use CSS classes or `data-*` attributes
- `catch { throw; }` — use `when` guard or let exceptions propagate
- Gold-plating: ARIA, wrapper divs, accessibility features not requested
- `_ = InvokeAsync(...)` — swallows exceptions; use `async void` + `DispatchExceptionAsync`
