:tocdepth: 2
Reactivity and effects
======================
Modern terms definition:
.. glossary::
reactive
In web frameworks, reactivity is the system that automatically updates the webpage (the UI) whenever
the underlying data (the state) changes.
imperative
The opposite model to reactivity is the imperative model (often referred to as manual DOM manipulation
in web development).
effects
In reactive web frameworks, effects (often called useEffect in React or watchEffect in Vue)
are functions that run automatically when the data they depend on changes. They are used to
sync your reactive data with systems outside the framework.
Fortunately, `pantra` supports **both** models: reactive and imperative. Second one by default.
.. note::
Despite imperative model is older at takes more code to manage, it makes logic much more explicitly obvious and
code running faster, avoiding implicit unwanted effects.
.. highlight:: pantra
Example of imperative logic::
Nothing
def action(node):
refs['message'].set_text("Hello there!")
Let's imaging we want to keep message in local context::
{{message}}
message: str = "Nothing"
def action(node):
ctx['message'] = "Hello there!"
refs['message'].update()
And this code could be simplified:
.. code-block::
:emphasize-lines: 1
!{{message}}
message: str = "Nothing"
def action(node):
ctx['message'] = "Hello there!"
Noticed exclamation mark (`!`) here? It informs engine to watch for `message` variable changes and then
update related node (`
` element).
It works the same for attributes expressions
.. code-block::
:emphasize-lines: 8
from pantra.ctx import *
x: int = 0
def action(node):
ctx['x'] = WebUnits(100)
And for :ref:`conditional ` nodes:
.. code-block::
:emphasize-lines: 1
!{{#if mode == "entry"}}
{{#else}}
Hello, {{user_name}}!
{{/if}}
mode: str = "entry"
user_name: str = ""
def action(node):
ctx["mode"] = "passed"
.. seealso::
Read more about :ref:`reactive macros `, :ref:`reactive attribute `
and :ref:`reactive tag `.
.. note::
Reactive variable names are extracted from the expression using :mod:`ast` parser. It means there is no
function call tracing for deeper variables changes. As example::
!{{get_message()}}
message: str = "Hello"
def get_message():
return message # <- variable "message" will no be tracked for changes
This was done consciously, to avoid possible mistakes from implicit variable changes tracking and further effects.
Better practise is to make reactions explicitly:
.. code-block::
:emphasize-lines: 2