Skip to content

Commit 9f10f80

Browse files
committed
work on intro to state section
1 parent 8114b2c commit 9f10f80

File tree

8 files changed

+157
-36
lines changed

8 files changed

+157
-36
lines changed

Diff for: docs/source/_exts/widget_example.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,12 @@ def _get_file_options(file: Path) -> list[str]:
122122
options = []
123123

124124
for line in file.read_text().split("\n"):
125-
file.name != "app.py" or print(repr(line))
126-
if line.strip() and not OPTION_PATTERN.match(line):
125+
if not line.strip():
126+
continue
127+
if not line.startswith("#"):
127128
break
129+
if not OPTION_PATTERN.match(line):
130+
continue
128131
option_string = line[1:].strip()
129132
if option_string:
130133
options.append(option_string)

Diff for: docs/source/adding-interactivity/components-with-state.rst

+133-15
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,145 @@ now let's just verify that this does in fact fix the problems from before:
8787
.. example:: adding_interactivity.adding_state_variable
8888
:activate-result:
8989

90-
.. _Your first hook:
9190

92-
.. dropdown:: :octicon:`light-bulb;2em` Your first hook
93-
:color: warning
94-
:open:
91+
Your First Hook
92+
---------------
9593

96-
In IDOM, ``use_state``, as well as any other function whose name starts with
97-
``use``, is called a "hook". These are special functions that should only be called
98-
while IDOM is :ref:`rendering <the-rendering-process>`. They let you "hook into" the
99-
different capabilities of IDOM's components of which ``use_state`` is just one (well
100-
get into the other :ref:`later <managing state>`).
94+
In IDOM, ``use_state``, as well as any other function whose name starts with ``use``, is
95+
called a "hook". These are special functions that should only be called while IDOM is
96+
:ref:`rendering <the rendering process>`. They let you "hook into" the different
97+
capabilities of IDOM's components of which ``use_state`` is just one (well get into the
98+
other :ref:`later <managing state>`).
10199

102-
While hooks are just normal functions, but it's helpful to think of them as
103-
:ref:`unconditioned <rules of hooks>` declarations about a component's needs. In
104-
other words, you'll "use" hooks at the top of your component in the same way you
105-
might "import" modules at the top of your Python files.
100+
While hooks are just normal functions, but it's helpful to think of them as
101+
:ref:`unconditioned <rules of hooks>` declarations about a component's needs. In other
102+
words, you'll "use" hooks at the top of your component in the same way you might
103+
"import" modules at the top of your Python files.
106104

107105

108-
Anatomy of ``use_state``
109-
------------------------
106+
Introduction to ``use_state``
107+
-----------------------------
110108

109+
When you call :func:`~idom.core.hooks.use_state` inside the body of a component's render
110+
function, you're declaring that this component needs to remember something. That
111+
"something" which needs to be remembered, is known as **state**. So when we look at an
112+
assignment expression like the one below
113+
114+
.. code-block::
115+
116+
index, set_index = use_state(0)
117+
118+
we should read it as saying that ``index`` is a piece of state which must be
119+
remembered by the component that declared it. The argument to ``use_state`` (in this
120+
case ``0``) is then conveying what the initial value for ``index`` is.
121+
122+
We should then understand that each time the component which owns this state renders
123+
``use_state`` will return a tuple containing two values - the current value of the state
124+
(``index``) and a function to change that value the next time the component is rendered.
125+
Thus, in this example:
126+
127+
- ``index`` - is a **state variable** containing the currently stored value.
128+
- ``set_index`` - is a **state setter** for changing that value and triggering a re-render
129+
of the component.
130+
131+
.. note::
132+
133+
The convention is that, if you name your state variable ``thing``, your state setter
134+
should be named ``set_thing``. While you could name them anything you want,
135+
adhereing to the convention makes things easier to understand across projects.
136+
137+
To understand how this works in context, let's break down our example:
138+
139+
.. tab-set::
140+
141+
.. tab-item:: 1
142+
143+
.. raw:: html
144+
145+
<h2>Initial render</h2>
146+
147+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
148+
:lines: 12-33
149+
:emphasize-lines: 2
150+
151+
.. tab-item:: 2
152+
153+
.. raw:: html
154+
155+
<h2>Initial state declaration</h2>
156+
157+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
158+
:lines: 12-33
159+
:emphasize-lines: 3
160+
161+
.. tab-item:: 3
162+
163+
.. raw:: html
164+
165+
<h2>Define event handler</h2>
166+
167+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
168+
:lines: 12-33
169+
:emphasize-lines: 5
170+
171+
.. tab-item:: 4
172+
173+
.. raw:: html
174+
175+
<h2>Return the view</h2>
176+
177+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
178+
:lines: 12-33
179+
:emphasize-lines: 16
180+
181+
.. tab-item:: 5
182+
183+
.. raw:: html
184+
185+
<h2>User interaction</h2>
186+
187+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
188+
:lines: 12-33
189+
190+
.. tab-item:: 6
191+
192+
.. raw:: html
193+
194+
<h2>Event handler triggers</h2>
195+
196+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
197+
:lines: 12-33
198+
:emphasize-lines: 6
199+
200+
.. tab-item:: 7
201+
202+
.. raw:: html
203+
204+
<h2>Next render begins</h2>
205+
206+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
207+
:lines: 12-33
208+
:emphasize-lines: 2
209+
210+
.. tab-item:: 8
211+
212+
.. raw:: html
213+
214+
<h2>Next state is acquired</h2>
215+
216+
.. literalinclude:: /_examples/adding_interactivity/adding_state_variable/app.py
217+
:lines: 12-33
218+
:emphasize-lines: 3
219+
220+
.. tab-item:: 9
221+
222+
**Repeat...**
223+
224+
...
225+
226+
.. hint::
227+
228+
Try clicking through the numbered tabs to each highlighted step of execution
111229

112230
Multiple State Declarations
113231
---------------------------

Diff for: docs/source/adding-interactivity/responding-to-events.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
Responding to Events
22
====================
33

4-
IDOM lets you add event handlers to your parts of the interface. This means that you can
5-
assign functions that are triggered when a particular user interaction occurs like
4+
IDOM lets you add event handlers to your parts of the interface. These events handlers
5+
are functions which can be assigned to a part of a UI such that, when a user iteracts
6+
with the interface, those functions get triggered. Examples of interaction include
67
clicking, hovering, of focusing on form inputs, and more.
78

89

Diff for: docs/source/creating-interfaces/your-first-components.rst

+7-7
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ Defining a Component
1313

1414
At their core, components are just normal Python functions that return HTML. To define a
1515
component you just need to add a ``@component`` `decorator
16-
<https://realpython.com/primer-on-python-decorators/>`__ to a function. Then, by
17-
convention, we name component functions like classes - with ``CamelCase``. So for
18-
example, if we wanted to write and then :ref:`display <Running IDOM>` a ``Photo``
19-
component we might write:
16+
<https://realpython.com/primer-on-python-decorators/>`__ to a function. Functions
17+
decorator in this way are known as **render function** and, by convention, we name them
18+
like classes - with ``CamelCase``. So for example, if we wanted to write, and then
19+
:ref:`display <Running IDOM>` a ``Photo`` component, we might write:
2020

2121
.. example:: creating_interfaces.simple_photo
2222
:activate-result:
2323

2424
.. warning::
2525

26-
If we had not decorated our ``Photo`` function with the ``@component`` decorator,
27-
the server would start, but as soon as we tried to view the page it would be blank.
28-
The servers logs would then indicate:
26+
If we had not decorated our ``Photo``'s render function with the ``@component``
27+
decorator, the server would start, but as soon as we tried to view the page it would
28+
be blank. The servers logs would then indicate:
2929

3030
.. code-block:: text
3131

Diff for: docs/source/developing-idom/changelog.rst

+4-5
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,10 @@ update deletes the original button.
347347
0.25.0
348348
------
349349

350-
Completely refactors :ref:`Layout Dispatchers <Layout Dispatcher>` by switching from a
351-
class-based approach to one that leverages pure functions. While the logic itself isn't
352-
any simpler, it was easier to implement, and now hopefully understand, correctly. This
353-
conversion was motivated by several bugs that had cropped up related to improper usage
354-
of ``anyio``.
350+
Completely refactors layout dispatcher by switching from a class-based approach to one
351+
that leverages pure functions. While the logic itself isn't any simpler, it was easier
352+
to implement, and now hopefully understand, correctly. This conversion was motivated by
353+
several bugs that had cropped up related to improper usage of ``anyio``.
355354

356355
**Issues Fixed:**
357356

Diff for: docs/source/escape-hatches/javascript-components.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ be using the ubiquitous React-based UI framework `Material UI`_.
4343

4444
So now that we can display a Material UI Button we probably want to make it do
4545
something. Thankfully there's nothing new to learn here, you can pass event handlers to
46-
the button just as you did when :ref:`getting started <handling events>`. Thus, all we
47-
need to do is add an ``onClick`` handler to the component:
46+
the button just as you did when :ref:`getting started <responding to events>`. Thus, all
47+
we need to do is add an ``onClick`` handler to the component:
4848

4949
.. example:: material_ui_button_on_click
5050

Diff for: docs/source/getting-started/running-idom.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ Presently IDOM's core library supports the following server implementations:
8888
- :mod:`idom.server.flask`
8989
- :mod:`idom.server.tornado`
9090

91-
.. note::
91+
.. hint::
9292

93-
To install them, see the ref:`Installing Other Servers` section.
93+
To install them, see the :ref:`Installing Other Servers` section.
9494

9595

9696
Available Server Types

Diff for: docs/source/index.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ To get a rough idea of how to write apps in IDOM, take a look at the tiny `"hell
5353
.. example:: hello_world
5454
:activate-result:
5555

56-
.. note::
56+
.. hint::
5757

5858
Try clicking the **▶️ result** tab to see what this displays!
5959

0 commit comments

Comments
 (0)