この時限を終えると、カードの下部に性別ごとの顧客数を示す横棒グラフが表示され、顧客を追加するたびに棒が伸びるようになります。Pythonでデータを加工して画面に表示する、データダッシュボードの基本パターンです。
Recharts(Reflexがラップして提供しているReactのチャートライブラリ)は、辞書のリストを受け取ります。辞書1つが棒1本に対応します。
# 手元にあるデータ # チャートが求めるデータ
[User(..., gender="Male"), [{"name": "Male", "value": 1},
User(..., gender="Female")] → {"name": "Female", "value": 1}]そのため、チャートを描く前に加工(集計)のステップが必要です。
from collections import Counter
class State(rx.State):
users: list[User] = [...]
users_for_graph: list[dict] = [] # チャート用のデータ
add_user_dialog_open: bool = False
@rx.event
def transform_data(self):
gender_counts = Counter(user.gender for user in self.users)
self.users_for_graph = [
{"name": gender_group, "value": count}
for gender_group, count in gender_counts.items()
]CounterはPythonの標準ライブラリです。Counter(["Male", "Female", "Male"]) → {"Male": 2, "Female": 1}。users_for_graphの初期値は空のリストです。2つのタイミングでデータを入れる必要があります。
ページを開いたとき:add_pageのon_loadにハンドラを登録します。
app.add_page(
index,
title="Customer Data App",
description="A simple app to manage customer data.",
on_load=State.transform_data, # ページを開くたび・再読み込みのたびに実行
)顧客を追加したとき:add_userの中から直接呼び出します。
@rx.event
def add_user(self, form_data: dict):
self.users.append(User(**form_data))
self.transform_data() # チャートのデータを再計算
self.add_user_dialog_open = Falsedescriptionは、検索エンジンやリンクのプレビューに表示されるページの説明(metaタグ)です。usersを変更するすべての場所でtransform_data()を忘れずに呼び出さなければならないことです。削除機能を追加するときに呼び出しを忘れると、チャートとテーブルの内容がずれてしまいます。@rx.varを付けると、「ほかの状態から計算される値」を宣言できます。usersが変わるたびに、Reflexが自動的に再計算してくれます。
class State(rx.State):
users: list[User] = [...]
@rx.var
def users_for_graph(self) -> list[dict]: # 戻り値の型アノテーションは必須
counts = Counter(user.gender for user in self.users)
return [{"name": g, "value": c} for g, c in counts.items()]transform_data、on_load、add_user内の呼び出しをすべて削除できます。画面のコード(data=State.users_for_graph)はそのままです。講師メモ — 「値を保存しておいて毎回更新する」か、「計算方法を宣言する」か。Excelでセルに値を直接入力するのと、数式(=COUNTIF(...))を入れるのとの違いにたとえると、よく伝わります。
def graph():
return rx.recharts.bar_chart(
rx.recharts.cartesian_grid(
horizontal=False, stroke_dasharray="3 3", stroke=rx.color("slate", 4)
),
rx.recharts.x_axis(
type_="number",
allow_decimals=False,
axis_line=False,
tick_line=False,
domain=[0, "dataMax + 1"],
),
rx.recharts.y_axis(
type_="category",
data_key="name",
axis_line=False,
tick_line=False,
width=64,
),
rx.recharts.bar(
data_key="value",
fill=rx.color("accent", 9),
radius=[0, 6, 6, 0],
bar_size=28,
),
data=State.users_for_graph,
layout="vertical",
width="100%",
height=160,
margin={"top": 0, "right": 16, "bottom": 0, "left": 0},
)チャートもコンポーネントです。部品を子要素として入れ、データやサイズはキーワード引数で指定します。
| 部品 | 役割 | 主な引数 |
|---|---|---|
bar_chart | チャート全体の枠 | data(辞書のリスト)、layout="vertical"(横棒) |
cartesian_grid | 背景のグリッド線 | horizontal=False(縦線のみ)、stroke_dasharray="3 3"(点線) |
x_axis | 横軸=顧客数 | type_="number"、allow_decimals=False(1.5人のような目盛りを防ぐ)、domain=[0, "dataMax + 1"](最大値より1だけ余裕を持たせる) |
y_axis | 縦軸=性別 | type_="category"、data_key="name"(辞書のどのキーを名前として使うか) |
bar | 棒 | data_key="value"(長さに使うキー)、radius=[0, 6, 6, 0](左上・右上・右下・左下の角。先端だけを丸める) |
layout="vertical"のときは、x軸が数値、y軸がカテゴリになります。縦棒(既定値)とは逆なので、いちばん混乱しやすいところです。rx.color("accent", 9)はテーマのアクセントカラーです。rxconfig.pyでRadixThemesPlugin(theme=rx.theme(accent_color="indigo"))のように変えると、ボタンと棒の色が一緒に変わります。graph()は、見出しの文言と一緒にカードの3番目の子要素として入れます。rx.box(
rx.text("Audience breakdown", size="3", weight="bold"),
rx.text(
"Customers by gender",
size="2",
color=rx.color("slate", 11),
margin_top="4px",
margin_bottom="20px",
),
graph(),
padding="24px",
),ブラウザで確認 — テーブルの下に「Audience breakdown」のエリアができ、MaleとFemaleの棒がそれぞれ1まで描かれます。x軸が2まであるのはdomain=[0, "dataMax + 1"]のためです。棒は左から伸びるアニメーションで表示されるので、1~2秒待ってみてください。
localhost:3000
操作してみようYour customer directory and audience breakdown.
Audience breakdown
Customers by gender
上のプレビューでFemaleの顧客を1人追加すると、Femaleの棒が2まで伸び、x軸が3まで広がります。チャートが変わらない場合は、add_userの中のself.transform_data()の呼び出しを確認してください。
5-5までの動作を確認できたら、画面はそのままにして、イベント方式をcomputed varに置き換えます。直すのは3か所です。
Stateからusers_for_graph: list[dict] = []のフィールドとtransform_dataメソッドを削除し、5-4の@rx.varメソッドを追加します。同じ名前が重複するので、フィールドは必ず削除してください。add_userの中のself.transform_data()の行を削除します。app.add_pageからon_load=State.transform_dataを削除します。class State(rx.State):
users: list[User] = [...]
add_user_dialog_open: bool = False
@rx.event
def set_add_user_dialog_open(self, open_: bool):
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 # transform_data()の呼び出しなし
@rx.var
def users_for_graph(self) -> list[dict]:
counts = Counter(user.gender for user in self.users)
return [{"name": g, "value": c} for g, c in counts.items()]
app = rx.App()
app.add_page(
index,
title="Customer Data App",
description="A simple app to manage customer data.",
) # on_loadなしgraph()のdata=State.users_for_graphは1文字も変えません。画面側から見ると、ふつうの状態変数もcomputed varも同じように見えます。from collections import Counterはそのまま残します。ブラウザで確認 — 保存するとホットリロードされ、チャートは5-5とまったく同じように表示されます。Femaleの顧客を追加して棒が2まで伸びれば、リファクタリングは成功です。一度も呼び出していないのに更新される、これがcomputed varの要点です。
rx.recharts.graphing_tooltip()をチャートの子要素として追加し、マウスを乗せると値が表示されるようにしてみましょう。@rx.var def female_count(self) -> intをもう1つ作り、チャートの見出しの横に「Female N人」と表示してみましょう。@より後ろ)ごとの顧客数チャートをもう1つ作ってみましょう。on_load方式とcomputed var方式の違いを説明できる。新しい授業・講座のお知らせを受け取る
この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。
R
ReflexKR
触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。
ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する
アフィリエイトと支援について© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
質問と回答
この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。