Reactive Expressions
In this section you will learn about pn.rx
. pn.rx
extends the concepts from pn.bind
that your learned in the previous section.
:::{note} You might feel some repetition from the previous section on pn.bind
. We do this on purpose to enable you to compare and contrast. pn.rx
is an extension of pn.bind
that provides more power and flexibility. pn.bind
has been the core API in Panel for a long time, so you will meet it across our documentation and community sites, and thus its very important to learn.
pn.rx
will enable you to build more complicated applications using a more flexible and maintainable architecture. :::
Embrace pn.rx
pn.rx
allows you to treat any object as a reactive expression. This means we can do things like multiplying a widget (representing the wind speed) with a float value (representing the efficiency) and then format the result all without writing callbacks:
You will notice how adding power_text
to the Column
displays both the widget and the bound function.
To separate the widget and bound function we can use the power_text
as a reference when we construct a Markdown
pane:
You can of course write expressions with multiple widgets. Lets make the efficiency
a widget:
Crafting Interactive Forms
Forms are powerful tools for collecting user inputs. With .rx.when
you can easily defer some calculation (i.e. the form submission) until some event (such as a button click) is triggered:
Try changing some of the inputs and clicking the submit Button. Try again. Notice how the text is only updated when we click the submit Button - we used .rx.when
to achieve this effect.
Harnessing Throttling for Performance
To prevent excessive updates and ensure smoother performance, you can apply throttling (.value_throttled
). This limits the rate at which certain actions or events occur, maintaining a balanced user experience:
Try dragging the slider. Notice that the text is only updated when you release the mouse.
Triggering Side Effects with .watch
When you need to trigger additional tasks in response to user actions, using .watch
comes in handy:
Here we store the state of the windturbine in a separate rx
variable, whenever the submit button is clicked we toggle the state.
:::{tip} When building apps using functions we recommend this approach to storing state. Applications are easier to reason about when the application displays according to the state instead of being changed directly. :::
Keep the UI responsive with threads or processes
To keep your UI and server responsive while the long running, blocking task is running you might want to run it asyncrounously in a separate thread:
:::{note} In the example we use a asyncio.to_thread
this should work great if your blocking task releases the GIL while running. Tasks that request data from the web or read data from files typically do this. Some computational methods from Numpy, Pandas etc. also release the GIL. If your long running task does not release the GIL you may have to use a ProcessPoolExecutor
instead. This introduces some overhead though. :::
Recommended Reading
We do recommend you study the explanation document about reactivity in Panel and the ReactiveExpr
reference guide to learn more about displaying reactive expressions in Panel.
Recap
You've now unlocked the power of interactivity in your Panel applications:
some_widget.rx()
: for seamless updates based on widget values.pn.rx(some_function)(widget_1, widget_2)
: for seamless updates based on widget values.pn.rx(some_task, some_widget).rx.watch()
: for triggering tasks in response to user actions.Throttling ensures smoother performance by limiting update frequency.
Utilizing async and threading keeps your UI responsive during long-running tasks.
Now, let your imagination run wild and craft dynamic, engaging Panel applications!