---
title: '条件レンダリング'
description: 'html! で if、if let、match を使った条件付きレンダリング'
---

import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'

## If ブロック

条件付きでマークアップをレンダリングするには、それを `if` ブロックでラップします：

<Tabs>
  <TabItem value="if" label="if">

```rust
use yew::prelude::*;

html! {
    if true {
        <p>{ "True case" }</p>
    }
};
```

  </TabItem>
  <TabItem value="if - else" label="if - else">

```rust
use yew::prelude::*;
let some_condition = true;

html! {
    if some_condition {
        <p>{ "True case" }</p>
    } else {
        <p>{ "False case" }</p>
    }
};
```

  </TabItem>
  <TabItem value="if let" label="if let">

```rust
use yew::prelude::*;
let some_text = Some("text");

html! {
    if let Some(text) = some_text {
        <p>{ text }</p>
    }
};
```

  </TabItem>
  <TabItem value="if let else" label="if let else">

```rust
use yew::prelude::*;
let some_text = Some("text");

html! {
    if let Some(text) = some_text {
        <p>{ text }</p>
    } else {
        <p>{ "False case" }</p>
    }
};
```

  </TabItem>
  <TabItem value="if-let-bindings" label="let バインディング">

ブレース付き本体では、html 子要素の前に `let` バインディングを使用でき、複数の子要素を直接記述できます：

```rust , ignore
use yew::prelude::*;

html! {
    if condition {
        let label = format!("count: {count}");
        <h2>{"Result"}</h2>
        <span>{label}</span>
    } else {
        "nothing"
    }
};
```

`let` バインディングはすべての html 子要素の前に記述する必要があり、交互に配置することはできません。

  </TabItem>
</Tabs>

## Match ブロック

`match` 式は `html!` 内で直接使用でき、`if`/`else` と同じパターンに従います：

<Tabs>
  <TabItem value="match" label="match">

```rust
use yew::prelude::*;

let value: Option<String> = Some("hello".into());

html! {
    match value {
        Some(text) => <p>{text}</p>,
        None => <p>{"Nothing here"}</p>,
    }
};
```

  </TabItem>
  <TabItem value="match-guards" label="if ガード">

```rust
use yew::prelude::*;

let value: i32 = 42;

html! {
    match value {
        x if x > 10 => <p>{"Big"}</p>,
        x if x > 0 => <p>{"Small"}</p>,
        _ => <p>{"Non-positive"}</p>,
    }
};
```

  </TabItem>
  <TabItem value="match-let" label="let バインディング">

ブレース付きのアーム本体では、`let` バインディングと複数の子要素を使用できます：

```rust , ignore
use yew::prelude::*;

html! {
    match data {
        Some(item) => {
            let label = format!("Item: {}", item.name);
            let class = if item.important { "highlight" } else { "normal" };
            <p class={class}>{label}</p>
        }
        None => <p>{"No data"}</p>,
    }
};
```

  </TabItem>
</Tabs>

単一要素のアームはブレースを省略できます。複数の子要素や `let` バインディングを持つアームにはブレースが必要です。

`match` は OR パターン（`A | B`）、分割代入、`if` ガードを含む、すべての標準的な Rust パターンをサポートします。網羅性は Rust コンパイラによってチェックされます。

## `if` / `match` の本体内部のループ

`if` / `else if` / `else` / `match` のアーム本体内部の `for`、`while`、`loop` は、`html!` のトップレベル位置と同じ規則に従いますが、一つだけ例外があります：ループ本体が完全に Rust として解析可能な場合（内部のどこにも html 要素がない場合）、マクロはそのループを html の制御フローではなく Rust の文として扱います。

もっとも遭遇しやすいのは、ループ本体に裸の `{expr}` ブロックしか書かれていないケースです：

```rust , ignore
// コンパイル可能。for はトップレベルにあり、html-`for` として解析されます。
html! {
    for _ in 0..9 {
        {my_foo}
    }
}

// コンパイル不可。for は `if` の内部にあり、Rust の文として解析されます。
// その後 rustc が、ループ本体の戻り型が `()` ではないと報告します。
html! {
    if condition {
        for _ in 0..9 {
            {my_foo}
        }
    }
}
```

子要素を html 要素で囲めば html-`for` の挙動が保たれます：

```rust , ignore
html! {
    if condition {
        for _ in 0..9 {
            <span>{my_foo}</span>
        }
    }
}
```

回避策の全体像は[リスト](./lists.mdx)を参照してください。
