Store Class¶
Container class for grouping observables and managing reactive state.
FynX Store - Reactive State Management Components¶
This module provides the core components for reactive state management in FynX, enabling you to create organized, reactive state containers that group related observables together with convenient subscription and state management methods.
Why Use Stores?¶
Stores help you organize your application's reactive state into logical units. Instead of having observables scattered throughout your codebase, Stores group related data together and provide convenient methods for subscribing to changes, serializing state, and managing the reactive lifecycle.
Stores are particularly useful for: - Application State: Global app state like user preferences, theme settings - Feature State: State for specific features like shopping cart, user profile - Component State: Local state that needs to be shared across multiple components - Business Logic: Computed values and derived state based on raw data
Core Components¶
Store: A base class for creating reactive state containers. Store classes can define
observable attributes using the observable()
descriptor, and automatically provide
methods for subscribing to changes and managing state.
observable: A descriptor function that creates observable attributes on Store classes. Use this to define reactive properties in your Store subclasses.
StoreSnapshot: An immutable snapshot of store state at a specific point in time, useful for debugging, logging, and ensuring consistent state access.
StoreMeta: A metaclass that automatically converts observable attributes to descriptors and provides type hint compatibility for mypy.
Key Features¶
- Automatic Observable Management: Store metaclass handles observable creation
- Convenient Subscriptions: Subscribe to all changes or individual observables
- State Serialization: Save and restore store state with
to_dict()
andload_state()
- Type Safety: Full type hint support for better IDE experience
- Memory Efficient: Automatic cleanup and efficient change detection
- Composable: Easy to combine and nest multiple stores
Basic Usage¶
from fynx import Store, observable
class CounterStore(Store):
count = observable(0)
name = observable("My Counter")
# Access values like regular attributes
print(CounterStore.count) # 0
CounterStore.count = 5 # Updates the observable
# Subscribe to all changes in the store
@CounterStore.subscribe
def on_store_change(snapshot):
print(f"Store changed: count={snapshot.count}, name={snapshot.name}")
CounterStore.count = 10 # Triggers: "Store changed: count=10, name=My Counter"
Advanced Patterns¶
Computed Properties in Stores¶
from fynx import Store, observable
class UserStore(Store):
first_name = observable("John")
last_name = observable("Doe")
age = observable(30)
# Computed properties using the >> operator
full_name = (first_name + last_name) >> (
lambda fname, lname: f"{fname} {lname}"
)
is_adult = age >> (lambda a: a >= 18)
print(UserStore.full_name) # "John Doe"
UserStore.first_name = "Jane"
print(UserStore.full_name) # "Jane Doe" (automatically updated)
State Persistence¶
# Save store state
state = CounterStore.to_dict()
# state = {"count": 10, "name": "My Counter"}
# Restore state later
CounterStore.load_state(state)
print(CounterStore.count) # 10
Store Composition¶
class AppStore(Store):
theme = observable("light")
language = observable("en")
class UserStore(Store):
name = observable("Alice")
preferences = observable({})
# Use both stores independently
AppStore.theme = "dark"
UserStore.name = "Bob"
Common Patterns¶
Singleton Stores: Use class-level access for global state:
class GlobalStore(Store):
is_loading = observable(False)
current_user = observable(None)
# Access globally
GlobalStore.is_loading = True
```
See Also¶
fynx.observable
: Core observable classes and operatorsfynx.computed
: Creating computed propertiesfynx.reactive
: Reactive decorators for side effectsfynx.watch
: Conditional reactive functions
Store ¶
Base class for reactive state containers with observable attributes.
Store provides a convenient way to group related observable values together
and manage their lifecycle as a cohesive unit. Store subclasses can define
observable attributes using the observable()
descriptor, and Store provides
methods for subscribing to changes, serializing state, and managing the
reactive relationships.
Key Features: - Automatic observable attribute detection and management - Convenient subscription methods for reacting to state changes - Serialization/deserialization support for persistence - Snapshot functionality for debugging and state inspection
Example
from fynx import Store, observable
class CounterStore(Store):
count = observable(0)
name = observable("Counter")
# Subscribe to all changes
@CounterStore.subscribe
def on_change(snapshot):
print(f"Counter: {snapshot.count}, Name: {snapshot.name}")
# Changes trigger reactions
CounterStore.count = 5 # Prints: Counter: 5, Name: Counter
CounterStore.name = "My Counter" # Prints: Counter: 5, Name: My Counter
Note
Store uses a metaclass to intercept attribute assignment, allowing
Store.attr = value
syntax to work seamlessly with observables.
StoreMeta ¶
Metaclass for Store to automatically convert observable attributes to descriptors and adjust type hints for mypy compatibility.
StoreSnapshot ¶
Immutable snapshot of store observable values at a specific point in time.
observable ¶
Create an observable with an initial value, used as a descriptor in Store classes.