2限目ではifの代わりにrx.condを、3限目ではforの代わりにrx.foreachを使いました。Pythonなのに、なぜPythonの文法をそのまま使えないのでしょうか?この回でその理由がわかると、Reflexで出会うエラーの大半がなぜ起きるのかを一度に理解できます。
Reflexアプリのコードは、異なる2つのタイミングで実行されます。
| コンパイル時 | 実行時 | |
|---|---|---|
| いつ | アプリの起動時に一度 | アプリが動いている間ずっと |
| 何が | 画面の関数(show_login、render_item …) | イベントハンドラ(increment、toggle_login …) |
| どこで | PythonのコードがJavaScript(React)のコードに変換される | サーバー上のPython |
| Stateの値 | まだわからない | 実際の値がある |
画面の関数は、アプリの起動時にJavaScriptへ変換されてブラウザに送られます。変換する時点では、どのユーザーが何を押すかはまだわからないので、画面の関数の中のLoginState.logged_inは実際のTrue/Falseではなく、「あとでブラウザで値が入る場所」です。この場所こそがVarです。
一方、イベントハンドラは変換されず、サーバー上でPythonのまま実行されます。そのため、ハンドラの中ではどんなPythonのコードやライブラリでも使えます。
下のハンドラはifを使い、State外に定義した関数も呼び出しています。実行時にサーバーで動くので、問題ありません。
def check_even(num: int):
return num % 2 == 0
class MyState3(rx.State):
count: int = 0
text: str = "even"
@rx.event
def increment(self):
# Use any Python code within state.
# Even reference functions defined outside the state.
if check_even(self.count):
self.text = "even"
else:
self.text = "odd"
self.count += 1
def count_and_check():
return rx.box(
rx.heading(MyState3.text, as_="h2"),
rx.button("Increment", on_click=MyState3.increment),
)localhost:3000
操作してみよう画面の関数の中でもPythonは使えます。ただし、使えるのはコンパイル時にすでに値が決まっているもの(state varを使わないもの)だけです。下のrange(5)とcheck_even(i)は、アプリの起動時に計算が終わります。
def show_numbers():
return rx.vstack(*[rx.text(f"{i} is {'even' if check_even(i) else 'odd'}") for i in range(5)])localhost:3000
実行画面0 is even
1 is odd
2 is even
3 is odd
4 is even
state varはコンパイル時には値がわからないので、画面の関数の中で次のコードはすべてエラーになります。
ifでVarの値を判定する:値が真か偽か、まだわかりません。propsの値を選ぶ場合も同じです。
class BadState(rx.State):
count: int = 0
def count_if_even():
return rx.box(
rx.heading("Count: ", as_="h2"),
# This will raise a compile error, as BadState.count is a var and not known at compile time.
rx.text(BadState.count if BadState.count % 2 == 0 else "Odd"),
# Using an if statement with a var as a prop will NOT work either.
rx.text("hello", color="red" if BadState.count % 2 == 0 else "blue"),
)forでリストのVarを回す:項目がいくつあるか、まだわかりません。
class BadState(rx.State):
items: list[str] = ["Apple", "Banana", "Cherry"]
def loop_over_list():
return rx.box(
# This will raise a compile error, as BadState.items is a list and not known at compile time.
*[rx.text(item) for item in BadState.items]
)len()のようなPythonの関数にVarを渡す:文字数を数えるための文字列が、まだありません。
class BadTextState(rx.State):
text: str = "Hello world"
def format_text():
return rx.box(
# Python operations such as `len` will not work on state vars.
rx.text(len(BadTextState.text)),
)では、画面で「偶数ならEven、奇数ならOdd」と表示するにはどうすればよいでしょうか?Reflexには、Varに対して使えるVar演算が用意されています。%、==、>のような演算子をVarに使うと、計算結果もVarになり、実際の計算はブラウザで値が入ったあとに行われます。
class CountEvenState(rx.State):
count: int = 0
@rx.event
def increment(self):
self.count += 1
def count_if_even():
return rx.box(
rx.heading("Count: ", CountEvenState.count, as_="h2"),
rx.cond(
# Here we use the `%` and `==` var operations to check if the count is even.
CountEvenState.count % 2 == 0,
rx.text("Even"),
rx.text("Odd"),
),
rx.button("Increment", on_click=CountEvenState.increment),
)localhost:3000
操作してみようEven
これで、1〜3限目で使った道具がなぜ必要だったのかが、1つの表にまとまります。
| やりたいこと | 画面のコードでは使えない | 代わりに使うもの |
|---|---|---|
| 条件に応じて違う画面を出す | if / else | rx.cond(条件, 真のとき, 偽のとき) |
| リストを繰り返す | for、リスト内包表記 | rx.foreach(リスト, 関数) |
| 長さを求める | len(x) | x.length() |
| 計算・比較 | Pythonの関数にVarを渡す | %、==、>などのVar演算 |
| 複雑な計算 | 画面の関数の中のPython | イベントハンドラで計算してStateに保存 |
ポイント — 迷ったときは「このコードはいつ実行されるの?」と自問してみてください。画面の関数の中ならコンパイル時なので、Varはまだ空の場所です。ハンドラの中なら実行時なので、本物の値が入っています。
format_textを直して、文字数が表示されるようにしてみましょう。ヒント:BadTextState.text.length()。count_if_evenで、countが10以上になったら「Big!」が表示されるようにしてみましょう。ヒント:rx.cond(CountEvenState.count >= 10, ...)。MyState3のようにハンドラの中で計算する方法と、CountEvenStateのようにVar演算を使う方法を比べてみましょう。State変数が少なくて済むのはどちらでしょうか?if、for、len()を使えない理由を説明できる。rx.cond、rx.foreachで同じことを実現する方法がわかる。新しい授業・講座のお知らせを受け取る
この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。
R
ReflexKR
触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。
ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する
アフィリエイトと支援について© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
質問と回答
この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。