Skip to content

State and rendering

use_state(initial) returns a value and setter. Updating state schedules React work; it does not change the value in an already-running render.

count, set_count = use_state(0)
set_count(lambda previous: previous + 1)

A callable passed as the initial value is a lazy initializer. A callable passed to the setter is a functional updater. Prefer a functional updater when the next value depends on previous state, including multiple queued updates.

Python objects are preserved

Lists, dictionaries and dataclasses can be state. The bridge retains Python objects through identity-preserving boxes rather than JSON-serializing every state update. Follow React's immutable update convention:

profile, set_profile = use_state({"name": "Ada", "active": False})
set_profile(lambda previous: {**previous, "active": True})

Mutating profile["active"] in place does not schedule an update. React compares the underlying state identity, so supply a new object when its meaning changes.

Reducers

def reducer(state, action):
    if action == "increment":
        return {**state, "count": state["count"] + 1}
    return state

state, dispatch = use_reducer(reducer, {"count": 0})

Reducers centralize related transitions. Dispatch sends an action; the reducer returns the next state. Keep the reducer pure.

Memoization and dependencies

use_memo(factory, dependencies) caches a computed result, and use_callback(fn, dependencies) preserves callback identity according to React. Do not use either to hide a correctness bug. Dependency entries are compared with React identity semantics; recreating a dict every render creates a new dependency even when its contents look identical.

See the hooks reference for transitions, deferred values and optimistic state.