R

ReflexKR

Reflex公式ドキュメント

Reflexで始めるPythonフルスタックWeb開発

·

講座の概要

1

Reflexの紹介と開発環境

2

コンポーネントで画面を描く

3

StateとVar:データに画面を描かせる

4

イベントとフォーム:顧客を追加する

5

データ加工とチャート

6

まとめ、デバッグ、次のステップ

·

付録

Reflexで始めるPythonフルスタックWeb開発
4限目

時間 2:10–2:55

イベントとフォーム:顧客を追加する

この時限を終えると、「Add User」ボタンでダイアログを開き、フォームを送信するとテーブルに顧客が追加されて、ダイアログが自動的に閉じるようになります。画面がユーザーの操作に反応する、最初にして最も重要なステップです。

4-1. イベントハンドラ (10分)

イベントハンドラとは、Stateの中に定義し、@rx.eventを付けたメソッドです。状態を変更できるのはイベントハンドラだけです。

class State(rx.State):
    users: list[User] = [...]

    @rx.event
    def add_user(self, form_data: dict):
        self.users.append(User(**form_data))
  • ハンドラはサーバー上の本物のPythonで実行されます。ここではself.usersはVarではなく実際のリストなので、append、len、if、for、さらには外部ライブラリまで自由に使えます。
  • self.usersを変更するとReflexがその変化を検知してブラウザに送り、テーブルとバッジが自動的に再描画されます。画面を直接書き換えるコードはありません。
  • User(**form_data)は、辞書を展開してキーワード引数として渡します。{"name": "Kim", "email": "...", "gender": "Male"} → User(name="Kim", email="...", gender="Male")。

講師メモ — 3限目の表と対比させてください。「画面の関数の中ではVarなのでlenは使えない。ハンドラの中では本物の値なのでlenが使える」。この対比がつかめれば、Reflexの半分は理解できたも同然です。

4-2. フォームを作る (10分)

rx.form(
    rx.flex(
        rx.input(placeholder="User Name", name="name", required=True),
        rx.input(placeholder="user@reflex.dev", name="email"),
        rx.select(
            ["Male", "Female"],
            placeholder="Select gender",
            default_value="Male",
            name="gender",
            custom_attrs={"aria-label": "Gender"},
        ),
        rx.flex(
            rx.dialog.close(
                rx.button("Cancel", type="button", variant="soft", color_scheme="gray"),
            ),
            rx.button("Submit", type="submit"),
            spacing="3",
            justify="end",
        ),
        direction="column",
        spacing="4",
    ),
    on_submit=State.add_user,
    reset_on_submit=False,
)
  • name=がすべてをつなぐ鍵です。送信すると、各入力欄のnameがキーになってform_data辞書が作られます。Userのフィールド名(name、email、gender)と完全に一致していないと、User(**form_data)は動きません。
  • on_submit=State.add_userには、ハンドラをクラス経由で、呼び出さずに渡します。フォームが作った辞書が自動的にform_dataに入ります。
  • required=Trueを付けると、送信前にブラウザが空欄をチェックしてくれます。
  • Cancelボタンのtype="button"が重要です。フォーム内のボタンは既定でsubmitになるため、これを忘れるとキャンセルを押しても顧客が追加されてしまいます。
  • rx.flexはdisplay="flex"のボックスです。direction="column"で縦に並び、spacingは間隔です。
  • custom_attrsは、Reflexが知らないHTML属性をそのまま付けたいときに使います。ここではスクリーンリーダー用のラベルです。

4-3. ダイアログで包む (10分)

def add_customer_button() -> rx.Component:
    return rx.dialog.root(
        rx.dialog.trigger(                       # 押すとダイアログが開く要素
            rx.button(
                rx.icon("plus", size=18),
                rx.text("Add User", size="2"),
            ),
        ),
        rx.dialog.content(                       # ダイアログの本体
            rx.dialog.title("Add New User"),
            rx.dialog.description("Fill the form with the user's info"),
            rx.form(...),                         # 4-2のフォーム
            max_width="450px",
        ),
    )
  • rx.icon("plus")には、Lucideのアイコン名をそのまま使います。
  • 作った関数は、ヘッダーの右側にadd_customer_button()として入れます(タイトルのboxの次、同じ親の中)。
  • 画面の部品を関数に分けるのは、ふつうのPythonの関数分割と同じです。特別な構文は必要ありません。

ブラウザで確認 — ヘッダーの右端に青い「+ Add User」ボタンが表示されます。

localhost:3000

操作してみよう

Customers

2

Your customer directory and audience breakdown.

NameEmailGender
Danilo Sousadanilo@example.comMale
Zahra Ambessazahra@example.comFemale
4-3の段階:Add Userを押して顧客を追加してみましょう。追加はされますが、ダイアログが閉じません。

ボタンを押すと背景が暗くなってダイアログが開き、性別は既定値のMaleが選択された状態になっています。上のプレビューで実際に値を入力し、Submitを押してみてください。

ここまでで実行してみると、問題が1つ見つかります。顧客は追加されるのに、ダイアログが閉じないのです。ダイアログの開閉をブラウザが単独で管理しているため、サーバーのハンドラから「閉じて」と伝える手段がないからです。

4-4. ダイアログを状態で制御する (10分)

解決策は、「開いているかどうか」をStateに移すことです。これを制御コンポーネント(controlled component)パターンと呼びます。

class State(rx.State):
    users: list[User] = [...]
    add_user_dialog_open: bool = False          # 1) 開閉状態をステートに持つ

    @rx.event
    def set_add_user_dialog_open(self, open_: bool):   # 2) セッターを自分で定義
        self.add_user_dialog_open = open_

    @rx.event
    def add_user(self, form_data: dict):
        self.users.append(User(**form_data))
        self.add_user_dialog_open = False      # 3) 送信したら閉じる
rx.dialog.root(
    ...,
    open=State.add_user_dialog_open,                  # ステートが開閉を決める
    on_open_change=State.set_add_user_dialog_open,    # ユーザーが開閉したらステートに反映
)
  • open=だけを指定してon_open_changeを忘れると、トリガーボタンを押しても状態が変わらず、ダイアログが開きません。この2つは必ずセットで使います。
  • on_open_changeは、開くときにTrue、閉じるとき(Cancel、ESC、外側のクリック)にFalseをハンドラに渡します。
  • Reflex 0.10には自動セッターがありません。古い資料にはState.set_変数名を定義せずに使うコードが多く見られますが、0.10ではそうしたメソッドは自動生成されないため、上のように自分で定義する必要があります。
  • 引数名をopen_にしているのは、Pythonの組み込み関数openと名前がぶつからないようにするための慣習です。
  • reset_on_submit=Falseですが、ダイアログが閉じると中身は画面から取り除かれ、次に開いたときに新しく描画されるので、入力欄は空の状態から始まります。

4-5. 1回のクリックがたどる道のり (5分)

  1. ユーザーがSubmitを押します。
  2. ブラウザが入力値を{"name": ..., "email": ..., "gender": ...}にまとめます。
  3. この値がWebSocketでサーバーに送られます。
  4. サーバーがそのユーザーのStateを見つけ、add_user(form_data)を実行します。
  5. 変化した変数(users、add_user_dialog_open)だけがブラウザに返ってきます。
  6. テーブルとバッジが再描画され、ダイアログが閉じます。

ブラウザで確認 — 4-4まで反映してからSubmitを押すと、ダイアログが閉じ、テーブルに3行目が追加されて、バッジが3に変わります。ダイアログが開いたままなら、4-4のopen=とon_open_change=をもう一度確認してください。

localhost:3000

操作してみよう

Customers

2

Your customer directory and audience breakdown.

NameEmailGender
Danilo Sousadanilo@example.comMale
Zahra Ambessazahra@example.comFemale
4限目の完成形:送信するとダイアログが閉じ、バッジの数字が増えます。

演習課題

  1. 性別の選択肢に"Other"を追加してみましょう。
  2. メールアドレスの入力欄にtype="email"を付け、不正な形式で送信するとどうなるか確認してみましょう。
  3. ハンドラで、名前が重複している場合は追加せずにreturn rx.toast.error("すでに登録されている顧客です")を返してみましょう。成功したときはrx.toast.success(...)も返してみてください。

チェックポイント

  • Add Userで顧客を追加すると、テーブルとバッジが更新される。
  • 送信後、ダイアログが自動的に閉じる。
  • Cancelを押しても顧客は追加されない。
  • name=、form_data、Userのフィールドの関係を説明できる。

← 前へ

3限目 · StateとVar:データに画面を描かせる

次へ →

5限目 · データ加工とチャート

新しい授業・講座のお知らせを受け取る

この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。

収集項目:メールアドレス・目的:この講座の新しい授業・公開のお知らせ・保有期間:解除のご依頼まで。他の目的には使わず、第三者にも提供しません。お知らせメールに返信いただければすぐに削除します。

質問と回答

この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。

リンクや書式なしで、そのままの文字で表示されます。

R

ReflexKR

触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。

ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する

アフィリエイトと支援について
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex