Reactive Web Dashboards with Shiny Transcripts
Chapter: Reactive effects and events
Lecture: Reactive event

Login or purchase this course to watch this video and the rest of the course contents.
0:00 Reactivity is a great default for a Shiny app because it will automatically update all of your outputs when a given input changes.
0:07 And most of the time, this is what you want.
0:09 But there are some cases where that type of eager evaluation, where your whole app re-executes, all of the elements re-execute whenever they need to,
0:17 isn't quite what you want, and you want to introduce a little bit more control. Here's an example of one such app.
0:23 So I have this data import function, and all I've done is made this function artificially slow. So there's just a little bit of a lag before it runs.
0:34 And when I run this function, this application, you'll see that it starts getting a little bit annoying to work with.
0:41 So I have this plot, and whenever I make a change here, it takes a second to update.
0:46 This is fine when you have a single interaction like this, but we actually have several things that we want to allow the user to filter.
0:55 So we can change the species, and oftentimes what the user is going to want to do is make several changes, like change this, change this, and change this,
1:04 and have some kind of button where they can say, ""Now apply all of the filters that I just did.
1:09 So instead of having this process re-render the plot four times, we might want to let the user batch that up so that they're able to just make a bunch of changes and then render the plot once.
1:22 And with reactivity without anything else, that's not really possible, right?
1:26 Because every time I make a change here, Shiny's going to invalidate everything that depends upon that input and then cause that recalculation to happen.
1:35 And it won't wait for the user to finish making all of their changes, because Shiny doesn't really know when the user is done making changes.
1:42 But we can use a tool called ReactiveEvent to allow Shiny to know that. Let's go ahead and do this.
1:48 So what I'm going to try to do is add a little button that just is a refresh button. First thing, we'll go and look at the Shiny website.
1:55 So the Shiny website has this nice little components gallery, and we can scroll down and there's an action button. Great.
2:03 So here's the code for the action button that we need. Go ahead and copy this. And I'm going to put this button right here in our sidebar.
2:15 So I'll call this refresh button. And the label is going to be refresh. So now I have this button. I can click it, but it doesn't do anything.
2:31 And in order to connect this button to something, I am going to use a ReactiveEvent decorator.
2:37 What the ReactiveEvent decorator does is it just says, Shiny, I don't want you to automatically detect dependencies for this node.
2:45 So instead of automatically detecting what this function asks for, I'm going to intervene and say the only thing that you should respond to is this refresh button.
2:57 Notice one important difference here.
2:59 So when we're calling inputs for their values, so in this case, I want the value of species at any given time or the value of mass at any given time.
3:07 When we in ReactiveEvent, we're actually just referring to the button itself. So we don't call this.
3:13 We just pass the reactive class as this, this reactive button into the ReactiveEvent decorator.
3:21 And so what this means is that this node is only going to recalculate when this button is pressed and everything downstream of it is still going to invalidate in the same way that it did before.
3:31 So I'll go ahead and save this. And now when the application opens up, nothing happens until you click refresh.
3:38 And then the plot is going to populate so I can make several different changes to this.
3:45 As many as I want, oh, maybe I decided I wanted to run the different species and then I click refresh and it's going to execute.
3:56 This is great, but that initial behavior maybe isn't quite what we want.
3:59 We might want to show the user the plot even when they haven't the first time, but not the second time. So there's a argument to ReactiveEvent.
4:07 All these decorators have arguments. And you see we have this ignore none. And so for buttons, that's the one we want. I think it's false.
4:20 So when we click ignore none equals false, that means that you're going to ignore it when it hasn't been clicked the first time.
4:28 And then it'll show the plot the first time, but then also require me to make some changes to it.
4:36 Even though this is introducing a kind of event handling to Shiny, it's important to note this is still taking place in that same reactive graph.
4:45 So even though this node is not automatically recalculating when its upstream elements change, it's still able to notify the downstream node that it should change.
4:57 So when we look at this render plotly decorator here, notice that we didn't put a ReactiveEvent here.
5:03 We didn't put something to say, ""Calculate this plot whenever this button changes.
5:08 Instead, we did it at the reactive calculation level and passed that value.
5:12 And that's able to notify the plot itself that it needs to recalculate when the button changes or when the reactive calc changes.
5:20 So it does work the same way. It's just kind of intervening in this one part of the reactive graph.
5:26 So ReactiveEvent is a great thing to have in your toolbox.
5:30 I think in general, you want to have Reactivity be the default for building these applications.
5:35 But sometimes you do need to intervene and override Reactivity to get the behavior you want. And ReactiveEvent is one important way of doing that.
5:43 One last thing to note about it is that ReactiveEvent can go under any decorator. So we can put it under ReactiveCalc here.
5:49 We could also put it under any of the plot or table rendering functions if we wanted to just control how those ones are rendered.
5:56 And lastly, and maybe most commonly, it's used in combination with ReactiveEffect to trigger side effects.
6:01 And that's what we're going to go through in the next lesson.


Talk Python's Mastodon Michael Kennedy's Mastodon