-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
input task button component entry #127
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Dan! I have a few comments, let me know if you have any follow-up questions or if I can help clarify anything.
@@ -0,0 +1,103 @@ | |||
--- | |||
title: Input Task Button |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
title: Input Task Button | |
title: Task Button |
The input task button is a special kind of button that allows long computations to not block | ||
the behaviour of the rest of the application. | ||
It looks very similar to the `ui.input_action_button()`, but uses the `ui.input_task_button()` function instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to massage the framing here a little bit, in particular to set up the UI and server steps, which are well differentiated below.
I think it's worth mentioning in the intro that input_task_button()
is a drop-in replacement for input_action_button()
. If used on its own, it will update when clicking on it starts a long-running computation to let users know that something is happening on the server.
But input_task_button()
is even more effective when paired with an extended task, which is something that happens on the server. Extended tasks run asynchronously and are truly non-blocking. The rest of your app can keep working while the extended task runs. An async function becomes an extended task with @reactive.extended_task
decorator and it can drive the button state with @ui.bind_task_button("btn_id")
. (You still have to react to the button click event, using something like @reactive.event(input.btn_id)
.)
(This is just a brainstorm/outline, feel free to modify/expand/etc.)
To create the separate function that makes the asynchronous computation: | ||
|
||
1. Import the built-in Python `asyncio` module | ||
2. Define a function that will be called in the button click step using the `async` and `await` syntax | ||
See the [coroutines and tasks](https://docs.python.org/3/library/asyncio-task.html) official Python documentation | ||
for details. | ||
3. Return the calculated result in the function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might be better to put this first. If I were teaching this interactively, I'd start by adding ui.input_task_button()
and then adding the @reactive.event(input.btn_id)
that reacts to the button click, and then finally showing the extended task.
But here, in static prose, I think that framing loses the priority of @reactive.extended_task
. It'd be better to talk about setting up the extended task and then secondarily to discuss that you still need to react to the button click event.
Also make sure that you mention the @reactive.extended_task
and @ui.bind_task_button()
decorators -- they're definitely more important than the standard @reactive.event()
and @reactive.effect
decorators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This app is a good technical demo -- see, it works! for people who already deeply understand reactivity.
I don't think it's a good example for actually demonstrating the value of the extended task. Most people will want to use extended tasks to kick off a long-running computation without preventing users from interacting with the rest of the app. In other words, there are fast tasks and slow tasks.
This example suffers from two problems:
- The fast task isn't driven by the user. In this example, the time updates, but I don't think the connection to "your app still runs" will be clear to learners.
- The slow task isn't (pretending) to be something the learner would actually do in their app.
I have three recommendations:
- Make sure the fast task involves the user directly interacting with the app.
- Make the slow task longer to give the user more time to see the overlapping work.
- Make the slow task at least appear to be something people would do, like build a model, read from a database, crunch some stats, hit an API, etc. (It doesn't have to actually do that, but it should pretend to.)
whoops! clicked an update button, the updated PR is coming in a bit! |
…-shiny-site into component_input_task_button
No description provided.