← スキル一覧に戻る

dioxus-component-patterns
by wchklaus97
A beautiful Progressive Web App (PWA) for managing reminders, built with Dioxus and Rust. Features include due dates, filtering, local storage, and offline support.
⭐ 1🍴 0📅 2026年1月24日
SKILL.md
name: dioxus-component-patterns description: Master Dioxus component patterns and reactive state management. Use when building Dioxus components, managing component state, or implementing component interactions.
Dioxus Component Patterns
Overview
This skill covers component patterns in Dioxus, including component structure, props, state management, event handling, and component composition.
Component Structure
Basic Component
use dioxus::prelude::*;
#[component]
fn ComponentName() -> Element {
rsx! {
div {
"Hello, World!"
}
}
}
Component with State
#[component]
fn Counter() -> Element {
let mut count = use_signal(|| 0);
rsx! {
div {
h1 { "Count: {count()}" }
button {
onclick: move |_| count.set(count() + 1),
"Increment"
}
}
}
}
Props Pattern
Simple Props
#[component]
fn Greeting(name: String) -> Element {
rsx! {
div {
"Hello, {name}!"
}
}
}
Props with Event Handlers
#[component]
fn ReminderCard(
reminder: Reminder,
on_toggle: EventHandler<String>,
on_delete: EventHandler<String>,
) -> Element {
let reminder_id = reminder.id.clone();
rsx! {
div {
class: "reminder-card",
h3 { "{reminder.title}" }
button {
onclick: move |_| on_toggle.call(reminder_id.clone()),
"Toggle"
}
button {
onclick: move |_| on_delete.call(reminder_id),
"Delete"
}
}
}
}
State Management Patterns
Local Component State
#[component]
fn Form() -> Element {
let mut title = use_signal(|| String::new());
let mut description = use_signal(|| String::new());
rsx! {
input {
value: "{title()}",
oninput: move |e| title.set(e.value())
}
}
}
Shared State via Props
#[component]
fn App() -> Element {
let mut reminders = use_signal(|| load_reminders());
rsx! {
ReminderList {
reminders: reminders(),
on_update: move |new_reminders| {
reminders.set(new_reminders);
}
}
}
}
Derived State
#[component]
fn ReminderStats(reminders: Vec<Reminder>) -> Element {
let total = reminders.len();
let completed = reminders.iter().filter(|r| r.completed).count();
let active = total - completed;
rsx! {
div {
"Total: {total}, Active: {active}, Completed: {completed}"
}
}
}
Event Handling Patterns
Inline Handlers
rsx! {
button {
onclick: move |_| {
count.set(count() + 1);
},
"Click"
}
}
Handler with Event Data
rsx! {
input {
oninput: move |e| {
title.set(e.value());
}
}
}
Handler with Cloned Data
#[component]
fn ReminderItem(reminder: Reminder, on_delete: EventHandler<String>) -> Element {
let reminder_id = reminder.id.clone();
rsx! {
button {
onclick: move |_| {
on_delete.call(reminder_id);
},
"Delete"
}
}
}
Conditional Rendering
Simple If
rsx! {
if show_form() {
AddReminderForm { on_add: move |r| { /* ... */ } }
}
}
If-Else
rsx! {
if reminders().is_empty() {
div { "No reminders yet" }
} else {
ReminderList { reminders: reminders() }
}
}
Ternary-like Pattern
rsx! {
div {
class: if is_active() { "active" } else { "inactive" },
"Content"
}
}
List Rendering
Simple List
rsx! {
for reminder in reminders().iter() {
ReminderCard {
reminder: reminder.clone(),
on_toggle: move |id| { /* ... */ },
}
}
}
List with Filter
rsx! {
for reminder in reminders().iter().filter(|r| !r.completed) {
ReminderCard { reminder: reminder.clone() }
}
}
List with Index
rsx! {
for (index, reminder) in reminders().iter().enumerate() {
ReminderCard {
reminder: reminder.clone(),
index: index,
}
}
}
Component Composition
Container Component
#[component]
fn App() -> Element {
let mut reminders = use_signal(|| load_reminders());
let mut show_form = use_signal(|| false);
rsx! {
div {
Header {
on_new_click: move |_| show_form.set(true)
}
if show_form() {
AddReminderForm {
on_add: move |r| { /* ... */ },
on_cancel: move |_| show_form.set(false),
}
}
ReminderList {
reminders: reminders(),
on_update: move |new| reminders.set(new),
}
}
}
}
Presentational Component
#[component]
fn ReminderList(
reminders: Vec<Reminder>,
on_update: EventHandler<Vec<Reminder>>,
) -> Element {
rsx! {
div {
class: "reminder-list",
for reminder in reminders.iter() {
ReminderCard {
reminder: reminder.clone(),
on_toggle: move |id| {
let mut updated = reminders.clone();
// Update logic
on_update.call(updated);
},
}
}
}
}
}
Form Patterns
Controlled Input
#[component]
fn TextInput(value: String, on_change: EventHandler<String>) -> Element {
rsx! {
input {
value: "{value}",
oninput: move |e| on_change.call(e.value())
}
}
}
Form with Validation
#[component]
fn AddReminderForm(on_add: EventHandler<Reminder>) -> Element {
let mut title = use_signal(|| String::new());
let mut error = use_signal(|| None::<String>);
rsx! {
div {
input {
value: "{title()}",
oninput: move |e| {
title.set(e.value());
if e.value().is_empty() {
error.set(Some("Title is required".to_string()));
} else {
error.set(None);
}
}
}
if let Some(err) = error() {
span { class: "error", "{err}" }
}
button {
disabled: title().is_empty(),
onclick: move |_| {
if !title().is_empty() {
on_add.call(Reminder { /* ... */ });
title.set(String::new());
}
},
"Add"
}
}
}
}
Best Practices
DO:
- ✅ Keep components small and focused
- ✅ Use descriptive component names
- ✅ Pass only necessary props
- ✅ Use
EventHandlerfor callbacks - ✅ Clone only what's needed in closures
- ✅ Use conditional rendering for UI states
- ✅ Use iterators for list rendering
DON'T:
- ❌ Don't create signals in render loops
- ❌ Don't mutate state directly (use
.set()) - ❌ Don't pass entire state to child components
- ❌ Don't create unnecessary clones
- ❌ Don't use indices when iterators work
- ❌ Don't mix concerns in components
Common Patterns
Loading State
let mut loading = use_signal(|| false);
rsx! {
if loading() {
div { "Loading..." }
} else {
ReminderList { reminders: reminders() }
}
}
Error State
let mut error = use_signal(|| None::<String>);
rsx! {
if let Some(err) = error() {
div { class: "error", "{err}" }
}
}
Toggle Pattern
let mut is_open = use_signal(|| false);
rsx! {
button {
onclick: move |_| is_open.set(!is_open()),
if is_open() { "Close" } else { "Open" }
}
if is_open() {
div { "Content" }
}
}
Resources
スコア
総合スコア
70/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
✓説明文
100文字以上の説明がある
+10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です