Calculate values and run automatic code¶
Use a computed value when one value can be calculated from other state. Use an effect when a state change should run code, such as updating several components or calling another API.
For a single component property, bind() is usually the
simpler choice.
Calculate a value from other state¶
Apply computed outside property:
from anvil_reactive.main import computed, reactive_class
@reactive_class
class OrderState:
def __init__(self):
self.price = 10
self.quantity = 2
@computed
@property
def total(self):
return self.price * self.quantity
Read order.total like any other property. Reactive remembers the result until
price or quantity changes.
A method decorated with @computed but not @property is also read as an
attribute, without parentheses.
Computed values should calculate and return a value. Use an effect for code that changes something outside the state object.
Run code when state changes¶
An effect runs once when Reactive sets it up, watches the reactive values it reads, and runs again after one of those values changes:
from anvil_reactive.main import effect
class OrderForm(OrderFormTemplate):
@effect
def update_order_summary(self):
self.total_label.text = f"Total: {self.order.total}"
self.item_count_label.text = len(self.order.items)
An effect method is still an ordinary callable method. You can call it directly when you need to run it immediately; Reactive manages its automatic runs.
Effects on Forms and components¶
An effect declared on an Anvil component follows that component's page lifetime:
- It waits until the component is added to the page before its first automatic run.
- It responds to state changes while the component is on the page.
- It continues to run if
visibleis set toFalsebut the component remains on the page. - It stops when the component is removed.
- If the component is added again, the effect starts again with the latest state.
This lets a Form own its UI updates without continuing to update after the Form has been closed or replaced.
Refresh an imperative component¶
Some components expose methods such as set_data() or refresh() instead of a
property that can be bound. A small version signal can tell an effect that the
component's external data is stale:
from anvil_reactive.main import effect, signal
class ResultsStore:
version = signal(0)
def mark_changed(self):
self.version += 1
class ResultsForm(ResultsFormTemplate):
@effect
def refresh_table(self):
_ = self.store.version
self.results_table.clear_cache()
self.results_table.set_data()
Call mark_changed() after a successful save, delete, or refresh. The signal
does not need to contain the table data; it only connects a change in your app
to the component's imperative update API. The _ = self.store.version line is
the read that makes the effect depend on that signal. Because the effect belongs
to the Form, it runs only while that Form is on the page.
render_effect remains available for existing apps and currently behaves like
effect. Prefer effect for new code.
Create an effect outside a class¶
Use create_effect() when an effect does not belong to an object:
from anvil_reactive.main import create_effect
@create_effect
def report_status():
print(state.status)
When an object or component should control the effect's lifetime, prefer an
@effect method.