CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-reactpy

Reactive user interfaces with pure Python

Pending
Overview
Eval results
Files

hooks.mddocs/

Hooks and State Management

React-style hooks for managing component state, side effects, and context in functional components. Hooks enable stateful logic in ReactPy components and must be called from within component functions.

Capabilities

State Hook

The use_state hook manages component state with a getter and setter pattern.

def use_state(initial_value: T | Callable[[], T]) -> tuple[T, Callable[[T], None]]: ...

Parameters:

  • initial_value: Initial state value or a function that returns the initial value

Returns: Tuple of (current_value, setter_function)

Usage Examples:

from reactpy import component, html, use_state

@component
def Counter():
    count, set_count = use_state(0)
    
    def increment():
        set_count(count + 1)
    
    def decrement():
        set_count(count - 1)
    
    return html.div(
        html.h1(f"Count: {count}"),
        html.button({"onClick": increment}, "Increment"),
        html.button({"onClick": decrement}, "Decrement")
    )

@component
def LazyInitialization():
    # Use function for expensive initial computation
    expensive_value, set_value = use_state(lambda: expensive_computation())
    return html.div(f"Value: {expensive_value}")

Effect Hook

The use_effect hook handles side effects with optional dependency tracking.

def use_effect(function: Callable[[], None | Callable[[], None]], dependencies: list[Any] | None = None) -> None: ...

Parameters:

  • function: Effect function, optionally returns cleanup function
  • dependencies: List of values that trigger re-execution when changed (None = every render, [] = once)

Usage Examples:

@component
def Timer():
    seconds, set_seconds = use_state(0)
    
    def setup_timer():
        interval_id = set_interval(lambda: set_seconds(seconds + 1), 1000)
        return lambda: clear_interval(interval_id)  # Cleanup function
    
    use_effect(setup_timer, [])  # Run once on mount
    
    return html.div(f"Timer: {seconds} seconds")

@component
def DocumentTitle(title: str):
    def update_title():
        document.title = title
    
    use_effect(update_title, [title])  # Run when title changes
    
    return html.h1(title)

Callback Hook

The use_callback hook memoizes callback functions to prevent unnecessary re-renders.

def use_callback(function: Callable[..., Any], dependencies: list[Any] | None = None) -> Callable[..., Any]: ...

Parameters:

  • function: Function to memoize
  • dependencies: List of values that invalidate the memoized callback

Usage Examples:

@component
def TodoList():
    todos, set_todos = use_state([])
    
    add_todo = use_callback(
        lambda text: set_todos([*todos, {"id": len(todos), "text": text}]),
        [todos]
    )
    
    return html.div(
        TodoForm({"onSubmit": add_todo}),
        *[TodoItem(todo, key=todo["id"]) for todo in todos]
    )

Memo Hook

The use_memo hook memoizes expensive computations.

def use_memo(function: Callable[[], T], dependencies: list[Any] | None = None) -> T: ...

Parameters:

  • function: Function that computes the value
  • dependencies: List of values that invalidate the memoized result

Usage Examples:

@component
def ExpensiveCalculation(numbers: list[int]):
    expensive_result = use_memo(
        lambda: sum(x**2 for x in numbers),
        [numbers]
    )
    
    return html.div(f"Sum of squares: {expensive_result}")

Ref Hook

The use_ref hook creates a mutable reference that persists across renders.

def use_ref(initial_value: T = None) -> Ref[T]: ...

class Ref[T]:
    current: T
    def __init__(self, initial_value: T = None): ...

Returns: Ref object with current attribute

Usage Examples:

@component
def FocusInput():
    input_ref = use_ref(None)
    
    def focus_input():
        if input_ref.current:
            input_ref.current.focus()
    
    return html.div(
        html.input({"ref": input_ref}),
        html.button({"onClick": focus_input}, "Focus Input")
    )

@component
def PreviousValue(value: int):
    previous_ref = use_ref(None)
    
    use_effect(lambda: setattr(previous_ref, 'current', value))
    
    return html.div(f"Current: {value}, Previous: {previous_ref.current}")

Reducer Hook

The use_reducer hook manages complex state with reducer pattern.

def use_reducer(
    reducer: Callable[[T, Any], T],
    initial_value: T,
    init: Callable[[T], T] | None = None
) -> tuple[T, Callable[[Any], None]]: ...

Parameters:

  • reducer: Function that takes (state, action) and returns new state
  • initial_value: Initial state value
  • init: Optional function to compute initial state lazily

Returns: Tuple of (current_state, dispatch_function)

Usage Examples:

def counter_reducer(state, action):
    if action["type"] == "increment":
        return state + 1
    elif action["type"] == "decrement":
        return state - 1
    elif action["type"] == "reset":
        return 0
    return state

@component
def CounterWithReducer():
    count, dispatch = use_reducer(counter_reducer, 0)
    
    return html.div(
        html.h1(f"Count: {count}"),
        html.button({"onClick": lambda: dispatch({"type": "increment"})}, "Increment"),
        html.button({"onClick": lambda: dispatch({"type": "decrement"})}, "Decrement"),
        html.button({"onClick": lambda: dispatch({"type": "reset"})}, "Reset")
    )

Context Hooks

Context hooks enable data sharing across component trees without prop drilling.

def create_context(default_value: T = None) -> Context[T]: ...
def use_context(context: Context[T]) -> T: ...

Usage Examples:

# Create context
ThemeContext = create_context("light")

@component
def ThemeProvider(*children, theme: str = "light"):
    return ThemeContext.Provider({"value": theme}, *children)

@component
def ThemedButton():
    theme = use_context(ThemeContext)
    
    return html.button(
        {"className": f"btn btn-{theme}"},
        "Themed Button"
    )

Specialized Hooks

Additional hooks for specific use cases:

def use_connection() -> Connection: ...
def use_location() -> Location: ...
def use_debug_value(value: Any, formatter: Callable[[Any], str] | None = None) -> None: ...
def use_scope() -> dict[str, Any]: ...
def use_exception() -> Callable[[Exception], None]: ...

Usage Examples:

@component
def ConnectionInfo():
    connection = use_connection()
    return html.div(f"Connected from: {connection.get('remote_addr')}")

@component
def LocationAware():
    location = use_location()
    return html.div(f"Current path: {location.get('pathname')}")

@component
def DebuggableComponent():
    count, set_count = use_state(0)
    use_debug_value(count, lambda c: f"Count: {c}")
    
    return html.div(f"Count: {count}")

Hook Rules

  1. Only call hooks from component functions - Never call hooks from regular functions, loops, or conditionals
  2. Call hooks in the same order - Don't call hooks inside loops, conditions, or nested functions
  3. Hook dependencies - Always include all values used inside effects in the dependency array
# ❌ Wrong - conditional hook
@component
def BadComponent(condition: bool):
    if condition:
        count, set_count = use_state(0)  # Don't do this
    return html.div()

# ✅ Correct - hooks at top level
@component
def GoodComponent(condition: bool):
    count, set_count = use_state(0)
    
    if condition:
        return html.div(f"Count: {count}")
    return html.div("No count")

Install with Tessl CLI

npx tessl i tessl/pypi-reactpy

docs

backend.md

components.md

configuration.md

events.md

hooks.md

html-elements.md

index.md

svg-elements.md

testing.md

vdom.md

web-modules.md

widgets.md

tile.json