reflex-dev

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Reflex Development

Reflex开发

Overview

概述

Reflex is a full-stack Python framework for building web applications without writing JavaScript. Apps compile to a React frontend and FastAPI backend, with state management and event handlers running entirely in Python.
Architecture:
  • Frontend: Compiled to React (JavaScript) for UI rendering
  • Backend: FastAPI server running Python event handlers
  • Communication: WebSockets for real-time state updates
  • State: Server-side Python state synchronized to frontend
Reflex是一款全栈Python框架,无需编写JavaScript即可构建Web应用。应用会编译为React前端和FastAPI后端,状态管理和事件处理程序完全在Python中运行。
架构:
  • 前端:编译为React(JavaScript)用于UI渲染
  • 后端:运行Python事件处理程序的FastAPI服务器
  • 通信:通过WebSockets实现实时状态更新
  • 状态:服务器端Python状态与前端同步

Core Concepts

核心概念

State Management

状态管理

State is a Python class that holds all mutable data and event handlers. All state variables must be JSON-serializable.
python
import reflex as rx

class AppState(rx.State):
    # State variables (any JSON-serializable type)
    count: int = 0
    items: list[str] = []
    user_name: str = ""

    # Event handlers - the ONLY way to modify state
    def increment(self):
        self.count += 1

    def add_item(self, item: str):
        self.items.append(item)

    # Computed vars (derived state)
    @rx.var
    def item_count(self) -> int:
        return len(self.items)
Key Rules:
  • State vars MUST be JSON-serializable (int, str, list, dict, bool, float)
  • Only event handlers can modify state
  • Use
    @rx.var
    decorator for computed/derived values
  • State is per-user session (isolated between users)
状态是一个Python类,包含所有可变数据和事件处理程序。所有状态变量必须可序列化为JSON。
python
import reflex as rx

class AppState(rx.State):
    # State variables (any JSON-serializable type)
    count: int = 0
    items: list[str] = []
    user_name: str = ""

    # Event handlers - the ONLY way to modify state
    def increment(self):
        self.count += 1

    def add_item(self, item: str):
        self.items.append(item)

    # Computed vars (derived state)
    @rx.var
    def item_count(self) -> int:
        return len(self.items)
关键规则:
  • 状态变量必须可序列化为JSON(int、str、list、dict、bool、float)
  • 只有事件处理程序可以修改状态
  • 使用
    @rx.var
    装饰器定义计算/派生值
  • 状态按用户会话隔离(不同用户之间互不干扰)

Components

组件

Components are UI building blocks. Reflex provides 60+ built-in components.
python
import reflex as rx

def header() -> rx.Component:
    return rx.heading("My App", size="lg")

def counter_component(state: AppState) -> rx.Component:
    return rx.vstack(
        rx.text(f"Count: {state.count}"),
        rx.button("Increment", on_click=state.increment),
        spacing="4"
    )
Common Components:
  • Layout:
    rx.vstack
    ,
    rx.hstack
    ,
    rx.box
    ,
    rx.container
  • Text:
    rx.heading
    ,
    rx.text
    ,
    rx.code
  • Input:
    rx.input
    ,
    rx.text_area
    ,
    rx.select
    ,
    rx.checkbox
  • Interactive:
    rx.button
    ,
    rx.link
    ,
    rx.icon_button
  • Data:
    rx.table
    ,
    rx.data_table
    ,
    rx.list
  • Charts:
    rx.recharts.line_chart
    ,
    rx.recharts.bar_chart
    , etc.
组件是UI的构建块。Reflex提供60+内置组件。
python
import reflex as rx

def header() -> rx.Component:
    return rx.heading("My App", size="lg")

def counter_component(state: AppState) -> rx.Component:
    return rx.vstack(
        rx.text(f"Count: {state.count}"),
        rx.button("Increment", on_click=state.increment),
        spacing="4"
    )
常用组件:
  • 布局:
    rx.vstack
    rx.hstack
    rx.box
    rx.container
  • 文本:
    rx.heading
    rx.text
    rx.code
  • 输入:
    rx.input
    rx.text_area
    rx.select
    rx.checkbox
  • 交互:
    rx.button
    rx.link
    rx.icon_button
  • 数据:
    rx.table
    rx.data_table
    rx.list
  • 图表:
    rx.recharts.line_chart
    rx.recharts.bar_chart

Event Handlers

事件处理程序

Event handlers respond to user interactions and are the ONLY way to modify state.
python
class FormState(rx.State):
    form_data: dict[str, str] = {}

    # Simple event handler
    def handle_submit(self):
        print(f"Submitted: {self.form_data}")

    # Event handler with argument
    def update_field(self, field: str, value: str):
        self.form_data[field] = value

    # Async event handler (for API calls, DB queries)
    async def fetch_data(self):
        # Can use any Python library
        import httpx
        async with httpx.AsyncClient() as client:
            response = await client.get("https://api.example.com/data")
            self.data = response.json()
Event Triggers (connect components to handlers):
  • on_click
    : Button clicks
  • on_change
    : Input field changes
  • on_submit
    : Form submissions
  • on_mount
    : Component first renders
  • on_blur
    ,
    on_focus
    : Input focus events
事件处理程序响应用户交互,是修改状态的唯一方式。
python
class FormState(rx.State):
    form_data: dict[str, str] = {}

    # Simple event handler
    def handle_submit(self):
        print(f"Submitted: {self.form_data}")

    # Event handler with argument
    def update_field(self, field: str, value: str):
        self.form_data[field] = value

    # Async event handler (for API calls, DB queries)
    async def fetch_data(self):
        # Can use any Python library
        import httpx
        async with httpx.AsyncClient() as client:
            response = await client.get("https://api.example.com/data")
            self.data = response.json()
事件触发器(连接组件与处理程序):
  • on_click
    :按钮点击
  • on_change
    :输入字段变更
  • on_submit
    :表单提交
  • on_mount
    :组件首次渲染
  • on_blur
    on_focus
    :输入框焦点事件

Project Structure

项目结构

Standard Reflex app structure:
my_app/
├── my_app/
│   ├── __init__.py         # Empty
│   └── my_app.py           # Main app file (State + pages)
├── assets/                 # Static files (images, fonts, etc.)
├── .web/                   # Auto-generated frontend (don't edit)
├── rxconfig.py             # Reflex configuration
└── requirements.txt        # Python dependencies
标准Reflex应用结构:
my_app/
├── my_app/
│   ├── __init__.py         # Empty
│   └── my_app.py           # Main app file (State + pages)
├── assets/                 # Static files (images, fonts, etc.)
├── .web/                   # Auto-generated frontend (don't edit)
├── rxconfig.py             # Reflex configuration
└── requirements.txt        # Python dependencies

Main App File Pattern

主应用文件模式

python
import reflex as rx
python
import reflex as rx

1. Define State

1. Define State

class State(rx.State): count: int = 0
def increment(self):
    self.count += 1
class State(rx.State): count: int = 0
def increment(self):
    self.count += 1

2. Define Pages

2. Define Pages

def index() -> rx.Component: return rx.container( rx.heading("Welcome"), rx.button("Click", on_click=State.increment), rx.text(f"Count: {State.count}") )
def about() -> rx.Component: return rx.container( rx.heading("About"), rx.link("Home", href="/") )
def index() -> rx.Component: return rx.container( rx.heading("Welcome"), rx.button("Click", on_click=State.increment), rx.text(f"Count: {State.count}") )
def about() -> rx.Component: return rx.container( rx.heading("About"), rx.link("Home", href="/") )

3. Create App and Add Routes

3. Create App and Add Routes

app = rx.App() app.add_page(index, route="/") app.add_page(about, route="/about")
undefined
app = rx.App() app.add_page(index, route="/") app.add_page(about, route="/about")
undefined

Common Patterns

常见模式

Form Handling

表单处理

python
class FormState(rx.State):
    name: str = ""
    email: str = ""

    def handle_submit(self, form_data: dict):
        self.name = form_data.get("name", "")
        self.email = form_data.get("email", "")

def form_page():
    return rx.form(
        rx.vstack(
            rx.input(name="name", placeholder="Name"),
            rx.input(name="email", placeholder="Email"),
            rx.button("Submit", type="submit"),
        ),
        on_submit=FormState.handle_submit,
    )
python
class FormState(rx.State):
    name: str = ""
    email: str = ""

    def handle_submit(self, form_data: dict):
        self.name = form_data.get("name", "")
        self.email = form_data.get("email", "")

def form_page():
    return rx.form(
        rx.vstack(
            rx.input(name="name", placeholder="Name"),
            rx.input(name="email", placeholder="Email"),
            rx.button("Submit", type="submit"),
        ),
        on_submit=FormState.handle_submit,
    )

Data Tables

数据表格

python
class DataState(rx.State):
    data: list[dict] = [
        {"id": 1, "name": "Alice", "age": 25},
        {"id": 2, "name": "Bob", "age": 30},
    ]

def data_table_page():
    return rx.data_table(
        data=DataState.data,
        columns=["id", "name", "age"],
        sort=True,
        search=True,
        pagination=True,
    )
python
class DataState(rx.State):
    data: list[dict] = [
        {"id": 1, "name": "Alice", "age": 25},
        {"id": 2, "name": "Bob", "age": 30},
    ]

def data_table_page():
    return rx.data_table(
        data=DataState.data,
        columns=["id", "name", "age"],
        sort=True,
        search=True,
        pagination=True,
    )

File Upload

文件上传

python
class UploadState(rx.State):
    async def handle_upload(self, files: list[rx.UploadFile]):
        for file in files:
            upload_data = await file.read()
            # Process file data
            outfile = f"./uploads/{file.filename}"
            with open(outfile, "wb") as f:
                f.write(upload_data)

def upload_page():
    return rx.vstack(
        rx.upload(
            rx.button("Select Files"),
            id="upload1",
        ),
        rx.button(
            "Upload",
            on_click=UploadState.handle_upload(rx.upload_files(upload_id="upload1"))
        ),
    )
python
class UploadState(rx.State):
    async def handle_upload(self, files: list[rx.UploadFile]):
        for file in files:
            upload_data = await file.read()
            # Process file data
            outfile = f"./uploads/{file.filename}"
            with open(outfile, "wb") as f:
                f.write(upload_data)

def upload_page():
    return rx.vstack(
        rx.upload(
            rx.button("Select Files"),
            id="upload1",
        ),
        rx.button(
            "Upload",
            on_click=UploadState.handle_upload(rx.upload_files(upload_id="upload1"))
        ),
    )

Database Integration (with DuckDB)

数据库集成(搭配DuckDB)

python
import duckdb
import polars as pl

class DBState(rx.State):
    records: list[dict] = []

    async def load_data(self):
        # Use existing database connection
        conn = duckdb.connect("data/mydb.duckdb")
        df = conn.execute("SELECT * FROM mytable").pl()
        self.records = df.to_dicts()
        conn.close()

    async def insert_record(self, data: dict):
        conn = duckdb.connect("data/mydb.duckdb")
        conn.execute(
            "INSERT INTO mytable (name, value) VALUES (?, ?)",
            [data["name"], data["value"]]
        )
        conn.close()
        await self.load_data()  # Refresh
python
import duckdb
import polars as pl

class DBState(rx.State):
    records: list[dict] = []

    async def load_data(self):
        # Use existing database connection
        conn = duckdb.connect("data/mydb.duckdb")
        df = conn.execute("SELECT * FROM mytable").pl()
        self.records = df.to_dicts()
        conn.close()

    async def insert_record(self, data: dict):
        conn = duckdb.connect("data/mydb.duckdb")
        conn.execute(
            "INSERT INTO mytable (name, value) VALUES (?, ?)",
            [data["name"], data["value"]]
        )
        conn.close()
        await self.load_data()  # Refresh

Styling & Layout

样式与布局

Inline Styling

内联样式

python
rx.box(
    rx.text("Styled text"),
    bg="#1a5f9e",
    color="white",
    padding="4",
    border_radius="md",
)
python
rx.box(
    rx.text("Styled text"),
    bg="#1a5f9e",
    color="white",
    padding="4",
    border_radius="md",
)

Responsive Layout

响应式布局

python
rx.container(
    rx.responsive_grid(
        rx.box("Item 1", bg="blue"),
        rx.box("Item 2", bg="green"),
        rx.box("Item 3", bg="red"),
        columns=[1, 2, 3],  # 1 col mobile, 2 tablet, 3 desktop
        spacing="4",
    ),
    max_width="1200px",
)
python
rx.container(
    rx.responsive_grid(
        rx.box("Item 1", bg="blue"),
        rx.box("Item 2", bg="green"),
        rx.box("Item 3", bg="red"),
        columns=[1, 2, 3],  # 1 col mobile, 2 tablet, 3 desktop
        spacing="4",
    ),
    max_width="1200px",
)

Common Style Props

常用样式属性

  • Layout:
    width
    ,
    height
    ,
    padding
    ,
    margin
    ,
    display
  • Colors:
    bg
    (background),
    color
    (text)
  • Typography:
    font_size
    ,
    font_weight
    ,
    text_align
  • Borders:
    border
    ,
    border_radius
    ,
    border_color
  • Spacing:
    spacing
    (for stacks),
    gap
  • 布局:
    width
    height
    padding
    margin
    display
  • 颜色:
    bg
    (背景色)、
    color
    (文字色)
  • 排版:
    font_size
    font_weight
    text_align
  • 边框:
    border
    border_radius
    border_color
  • 间距:
    spacing
    (用于堆叠组件)、
    gap

Routing

路由

Multiple Pages

多页面配置

python
app = rx.App()
python
app = rx.App()

Route with parameters

Route with parameters

@rx.page(route="/user/[id]") def user_page() -> rx.Component: return rx.text(f"User ID: {State.router.page.params.get('id')}")
@rx.page(route="/user/[id]") def user_page() -> rx.Component: return rx.text(f"User ID: {State.router.page.params.get('id')}")

Simple routes

Simple routes

app.add_page(index, route="/") app.add_page(about, route="/about")
undefined
app.add_page(index, route="/") app.add_page(about, route="/about")
undefined

Navigation

导航

python
undefined
python
undefined

Links

Links

rx.link("Go to About", href="/about")
rx.link("Go to About", href="/about")

Programmatic navigation

Programmatic navigation

def go_home(self): return rx.redirect("/")
undefined
def go_home(self): return rx.redirect("/")
undefined

Development Workflow

开发工作流

Initialize New App

初始化新应用

bash
pip install reflex
reflex init
bash
pip install reflex
reflex init

Run Development Server

运行开发服务器

bash
reflex run
App runs on
http://localhost:3000
with auto-reload.
bash
reflex run
应用将在
http://localhost:3000
运行,支持自动重载。

Common Commands

常用命令

bash
reflex run          # Start dev server
reflex export       # Build production bundle
reflex db init      # Initialize database (if using Reflex DB)
reflex db migrate   # Run migrations
bash
reflex run          # Start dev server
reflex export       # Build production bundle
reflex db init      # Initialize database (if using Reflex DB)
reflex db migrate   # Run migrations

Best Practices

最佳实践

  1. State Organization: Split large states into substates
    python
    class AuthState(rx.State):
        user: str = ""
    
    class DataState(rx.State):
        items: list = []
  2. Component Reusability: Create reusable component functions
    python
    def card(title: str, content: str) -> rx.Component:
        return rx.box(
            rx.heading(title, size="md"),
            rx.text(content),
            padding="4",
            border="1px solid #ddd",
        )
  3. Event Handler Performance: Use async for I/O operations
    python
    async def fetch_data(self):
        # Async I/O won't block other users
        self.data = await some_api_call()
  4. Type Hints: Always type-hint state vars and event handlers
    python
    count: int = 0
    items: list[str] = []
    
    def update_count(self, value: int) -> None:
        self.count = value
  1. 状态组织:将大型拆分为子状态
    python
    class AuthState(rx.State):
        user: str = ""
    
    class DataState(rx.State):
        items: list = []
  2. 组件复用:创建可复用的组件函数
    python
    def card(title: str, content: str) -> rx.Component:
        return rx.box(
            rx.heading(title, size="md"),
            rx.text(content),
            padding="4",
            border="1px solid #ddd",
        )
  3. 事件处理程序性能:对I/O操作使用异步
    python
    async def fetch_data(self):
        # Async I/O won't block other users
        self.data = await some_api_call()
  4. 类型提示:始终为状态变量和事件处理程序添加类型提示
    python
    count: int = 0
    items: list[str] = []
    
    def update_count(self, value: int) -> None:
        self.count = value

References

参考资料

Documentation

文档

Example Apps

示例应用

See
examples/
directory for complete working examples:
  • Simple counter app
  • Data table with CRUD operations
  • Form with validation
  • File upload and processing
查看
examples/
目录获取完整的可运行示例:
  • 简单计数器应用
  • 带CRUD操作的数据表格
  • 带验证的表单
  • 文件上传与处理

Common Patterns Reference

常见模式参考

See
references/patterns.md
for detailed examples of:
  • Authentication flows
  • Real-time updates
  • Complex form validation
  • Multi-step workflows
  • Data visualization with charts
查看
references/patterns.md
获取以下场景的详细示例:
  • 认证流程
  • 实时更新
  • 复杂表单验证
  • 多步骤工作流
  • 图表数据可视化