Skip to content

Store

A Store holds one immutable application value outside the component tree. Actions replace the value with store.set(...) or store.update(...), and components read it with use_store, re-rendering only when the selected slice changes.

from dataclasses import dataclass, replace

import pythonnative as pn


@dataclass(frozen=True)
class Session:
    user: str | None = None
    unread: int = 0


session = pn.Store(Session())


def sign_in(user: str) -> None:
    session.update(lambda state: replace(state, user=user))


@pn.component
def UnreadBadge() -> pn.Node:
    unread = pn.use_store(session, lambda state: state.unread)
    return pn.Text(str(unread)) if unread else None

Application state that lives outside the component tree.

A Store holds one immutable value (typically a frozen dataclass) and notifies subscribers when it's replaced. Components read it with use_store, optionally through a selector, and re-render only when the selected value changes:

from dataclasses import dataclass, replace

import pythonnative as pn


@dataclass(frozen=True)
class Session:
    user: str | None = None
    unread: int = 0


session = pn.Store(Session())


def sign_in(user: str) -> None:
    session.update(lambda state: replace(state, user=user))


@pn.component
def UnreadBadge() -> pn.Node:
    unread = pn.use_store(session, lambda state: state.unread)
    return pn.Text(str(unread)) if unread else None

Stores are plain objects: define them at module level, pass them through context, or own them in a service. Actions are ordinary functions. Because the value is replaced rather than mutated, every change is visible to the framework's equality rule, and tests can drive a store without rendering anything.

Classes:

Name Description
Store

A replaceable value with change notifications.

Functions:

Name Description
use_store

Read store (or selector(store.get())) and re-render when it changes.

Store

Store(initial: T, *, name: Optional[str] = None)

Bases: Generic[T]

A replaceable value with change notifications.

Writes apply immediately under a lock, so get() always returns the latest value on every thread. Listeners run synchronously on the writing thread after the value changes; components subscribed through use_store schedule their re-render on the application thread, like any state setter.

Parameters:

Name Type Description Default
initial T

The starting value.

required
name Optional[str]

Optional label shown in repr and diagnostics.

None

Methods:

Name Description
get

Return the current value.

set

Replace the value; subscribers are notified only when it changed.

update

Replace the value with fn(current), atomically with respect to other writers.

subscribe

Call listener() after every change; returns a function that unsubscribes.

batch

Coalesce the writes inside the block into at most one notification.

get

get() -> T

Return the current value.

set

set(value: T) -> None

Replace the value; subscribers are notified only when it changed.

update

update(fn: Callable[[T], T]) -> None

Replace the value with fn(current), atomically with respect to other writers.

subscribe

subscribe(
    listener: Callable[[], None],
) -> Callable[[], None]

Call listener() after every change; returns a function that unsubscribes.

batch

batch() -> Iterator['Store[T]']

Coalesce the writes inside the block into at most one notification.

with store.batch():
    store.update(add_item)
    store.update(bump_revision)

use_store

use_store(store: Store[T]) -> T
use_store(
    store: Store[T], selector: Callable[[T], S]
) -> S
use_store(
    store: Store[T],
    selector: Optional[Callable[[T], S]] = None,
) -> T | S

Read store (or selector(store.get())) and re-render when it changes.

The component subscribes on mount and unsubscribes on unmount. With a selector it re-renders only when the selected value changes under the framework's equality rule, so a component that shows a count doesn't re-render when an unrelated field changes. The selector may be a fresh lambda on every render.

Parameters:

Name Type Description Default
store Store[T]

The Store to read.

required
selector Optional[Callable[[T], S]]

Optional state -> value projection.

None

Returns:

Type Description
T | S

The store's value, or the selected projection of it.

Raises:

Type Description
RuntimeError

If called outside a @component function.

Next steps