@@ -154,27 +154,54 @@ Async Effects
154154.............
155155
156156A behavior unique to ReactPy's implementation of ``use_effect `` is that it natively
157- supports ``async `` functions:
157+ supports ``async `` effects. Async effect functions may either be an async function
158+ or an async generator. If your effect doesn't need to do any cleanup, then you can
159+ simply write an async function.
158160
159161.. code-block ::
160162
161163 async def non_blocking_effect():
162- resource = await do_something_asynchronously()
163- return lambda: blocking_close(resource)
164+ await do_something()
164165
165166 use_effect(non_blocking_effect)
166167
168+ However, if you need to do any cleanup, then you must ``yield False `` inside a try-finally
169+ block and place your cleanup logic in the finally block. Yielding ``False `` indicates to
170+ ReactPy that the effect will not yield again before it is cleaned up.
167171
168- There are **three important subtleties ** to note about using asynchronous effects:
172+ .. code-block ::
173+
174+ async def blocking_effect():
175+ await do_something()
176+ try:
177+ yield False
178+ finally:
179+ await do_cleanup()
169180
170- 1. The cleanup function must be a normal synchronous function.
181+ use_effect(blocking_effect)
171182
172- 2. Asynchronous effects which do not complete before the next effect is created
173- following a re-render will be cancelled. This means an
174- :class: `~asyncio.CancelledError ` will be raised somewhere in the body of the effect.
183+ If you have a long-lived effect, you may ``yield True `` multiple times. ``True `` indicates
184+ to ReactPy that the effect will yield again if the effect doesn't need to be cleanup up
185+ yet.
186+
187+ .. code-block ::
188+
189+ async def establish_connection():
190+ connection = await open_connection()
191+ try:
192+ while True:
193+ yield False
194+ await connection.send(create_message())
195+ handle_message(await connection.recv())
196+ finally:
197+ await close_connection(connection)
198+
199+ use_effect(non_blocking_effect)
175200
176- 3. An asynchronous effect may occur any time after the update which added this effect
177- and before the next effect following a subsequent update.
201+ Note that, if an effect needs to be cleaned up, it will only do so when the effect
202+ function yields control back to ReactPy. So you should ensure that either, you can
203+ be sure that the effect will yield in a timely manner, or that you enforce a timeout
204+ on the effect. Otherwise, ReactPy may hang while waiting for the effect to yield.
178205
179206
180207Manual Effect Conditions
0 commit comments