Substates
Substates allow you to break up your state into multiple classes to make it more manageable. This is useful as your app grows, as it allows you to think about each page as a separate entity. Substates also allow you to share common state resources, such as variables or event handlers.
When a particular state class becomes too large, breaking it up into several substates can bring performance benefits by only loading parts of the state that are used to handle a certain event.
Multiple States
One common pattern is to create a substate for each page in your app. This allows you to think about each page as a separate entity, and makes it easier to manage your code as your app grows.
To create a substate, simply inherit from rx.State
multiple times:
Separating the states is purely a matter of organization. You can still access the state from other pages by importing the state class.
State Inheritance
A substate can also inherit from another substate other than rx.State
, allowing you to create a hierarchy of states.
For example, you can create a base state that defines variables and event handlers that are common to all pages in your app, such as the current logged in user.
You can access the parent state properties from a child substate automatically.
Accessing Arbitrary States
An event handler in a particular state can access and modify vars in another state instance by calling
the get_state
async method and passing the desired state class. If the requested state is not already loaded,
it will be loaded and deserialized on demand.
In the following example, the GreeterState
accesses the SettingsState
to get the salutation
and uses it
to update the message
var.
Notably, the widget that sets the salutation does NOT have to load the GreeterState
when handling the
input on_change
event, which improves performance.
Performance Implications
When an event handler is called, Reflex will load the data not only for the substate containing the event handler, but also all of its substates and parent states as well. If a state has a large number of substates or contains a large amount of data, it can slow down processing of events associated with that state.
For optimal performance, keep a flat structure with most substate classes directly inheriting from rx.State
.
Only inherit from another state when the parent holds data that is commonly used by the substate.
Implementing different parts of the app with separate, unconnected states ensures that only the necessary
data is loaded for processing events for a particular page or component.
Avoid defining computed vars inside a state that contains a large amount of data, as
states with computed vars are always loaded to ensure the values are recalculated.
When using computed vars, it better to define them in a state that directly inherits from rx.State
and
does not have other states inheriting from it, to avoid loading unnecessary data.