Skip to content

Commit e35c8ad

Browse files
committed
add more to state as snapshot
1 parent 6eb9631 commit e35c8ad

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from idom import component, html, run, use_state
2+
3+
4+
@component
5+
def Counter():
6+
number, set_number = use_state(0)
7+
8+
def handle_click(event):
9+
set_number(number + 1)
10+
set_number(number + 1)
11+
set_number(number + 1)
12+
13+
return html.div(
14+
html.h1(number),
15+
html.button({"onClick": handle_click}, "Increment"),
16+
)
17+
18+
19+
run(Counter)

docs/source/adding-interactivity/state-as-a-snapshot.rst

+58-5
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,65 @@ sent!":
99

1010
.. image:: _static/direct-state-change.png
1111

12-
IDOM works a bit differently though. Previously, you'll have seen how, in order to
13-
change the view you need to :ref:`"set state" <Introduction to use_state>`. Doing so
14-
then triggers a re-render of the view.
12+
IDOM works a bit differently though - user interactions cause event handlers to
13+
:ref:`"set state" <Introduction to use_state>` triggering IDOM to re-render a new
14+
version of the view rather then mutating the existing one.
1515

1616
.. image:: _static/idom-state-change.png
1717

18-
...
18+
Given this, when IDOM "renders" something, it's as if IDOM has taken a snapshot of the
19+
UI where all the event handlers, local variables and the view itself were calculated
20+
using what state was present at the time of that render. Then, when user iteractions
21+
trigger state setters, IDOM is made away of the newly set state and schedules a
22+
re-render. When this subsequent renders occurs it performs all the same calculations as
23+
before, but with this new state.
1924

20-
.. idom:: _examples/send_message
25+
As we've :ref:`already seen <When Variables Aren't Enough>`, state variables are not
26+
like normal variables. Instead, they live outside your components and are managed by
27+
IDOM. When a component is rendered, IDOM provides the component a snapshot of the state
28+
in that exact moment. As a result, the view returned by that component is itself a
29+
snapshot of the UI at that time.
30+
31+
32+
Investigating State Snapshots
33+
-----------------------------
34+
35+
Let's experiment with some potentially less intuitive behaviors of state to see why we
36+
should think about it with respect to these "snapshots" in time. Take a look at the
37+
example below and try to guess how it will behave. **What will the count be after you
38+
click the "Increment" button?**
39+
40+
.. idom:: _examples/set_counter_3_times
41+
42+
Despite the fact that we called ``set_count(count + 1)`` three times, the count only
43+
increments by ``1``! This is perhaps a surprising result, but let's break what's
44+
happening inside the event handler to see why this is happening:
45+
46+
.. code-block::
47+
48+
set_count(count + 1)
49+
set_count(count + 1)
50+
set_count(count + 1)
51+
52+
On the initial render of your ``Counter`` the ``number`` variable is ``0``. So we ought
53+
to be able to substitute ``number`` with ``0`` everywhere it's referenced within the
54+
component. Since that includes the event handler too we should be able to rewrite the
55+
three lines above as:
56+
57+
.. code-block::
58+
59+
set_count(0 + 1)
60+
set_count(0 + 1)
61+
set_count(0 + 1)
62+
63+
Even though, we called ``set_count`` three times, every time we were actually just
64+
doing ``set_count(1)`` three times. Only after the event handler returns will IDOM
65+
actually perform the next render where count is ``1``. When it does, ``number`` will be
66+
``1`` and we'll be able to perform the same subtitution as before to see what the next
67+
number will be after we click "Increment":
68+
69+
.. code-block::
70+
71+
set_count(1 + 1)
72+
set_count(1 + 1)
73+
set_count(1 + 1)

0 commit comments

Comments
 (0)