Reactive Web Dashboards with Shiny Transcripts
Chapter: Reactivity
Lecture: Reactive calc example
Login or
purchase this course
to watch this video and the rest of the course contents.
0:00
Now that we've learned a little bit about how reactivity and reactive calculations work,
0:05
let's take a concrete example to know when we should apply them to our, to, or when you should apply them to your own code.
0:10
So here is a example application, and we have two inputs here that both filter us the same dataset, and that dataset is used by both of these plots.
0:21
When we go over and look at the code, the first thing that should trigger that you should use a
0:28
reactive calculation is just when you see any type of repetition, whenever you maybe copy and paste
0:34
some code or use the same basic logic in two places. So for example, in this case, I've got
0:41
this subset happening, and this subset takes the data frame and selects the species that are in
0:47
input species and the body mass that is lower than input mass. And down here when I'm returning the
0:53
table, I'm doing the exact same thing. This is the same code down from line 48 to 51 as up here,
0:59
26 to 29. And this causes two problems. So the first problem is that there might be a mismatch
1:07
between this code and this code. Maybe I make a change, add in some other filter in this data
1:13
frame, but forget to do it up here in the plot. That might cause my application to be out of sync
1:19
with itself. The plot and the table are not showing the same data, which can be confusing for
1:23
the user. But the second main reason is that this is being run twice. So it's being run once when
1:29
the render plot function fires, and then again when the render data frame function fires.
1:35
And to prove that, I'll just start by extracting this into a regular Python function. So I'll call
1:43
this filter data, and it's just going to return this filter here. And I'll add a print statement so that we can know when it's used.
2:02
And I will replace this call here with a call to the filter data function.
2:08
All right, so I haven't actually changed anything about this code. I'm just using a function
2:16
to do the subsetting instead of calling it twice. But this will let us look in our terminal and see
2:24
that this firing is happening two times. So when I make a change, so when it first loads up,
2:32
it's doing the filter once for the plot and again for the table. And if I make any kind of change
2:37
here, it's always going to be firing two times because the filter is happening twice. So it's
2:43
not taking advantage of any of that fancy caching behavior that we went through in the last exercise.
2:48
The way to get it to take advantage of that is to decorate this function with a reactive calc
2:55
decorator. And the reactive calc decorator is in the reactive submodule, which is imported from
3:01
the main Shiny module. So it's not from Shiny Express, it's from just the base Shiny package.
3:07
I've already imported reactive here, and then I can decorate this function with reactive calc.
3:14
And this is where all of the functions that all the methods that manage reactivity
3:18
are stored in the reactive calc module. I'll still have that firing function there.
3:25
And since we decorated it, maybe I'll save it to actually get that to load.
3:33
Now when I've decorated it, you see this is only happening once. So if I make a change to the
3:39
body mass, it's only doing the filter one time and then passing that same filter to plot and table.
3:45
So this is a little bit different than probably how you would program outside of a web application.
3:56
Like if you were just writing a Python script, you might tolerate some repetition. Maybe you
3:59
extract a function after you repeat yourself three or four times. But with Shiny, you really benefit
4:04
from being pretty strict about not repeating yourself. So anytime you see some repeated code
4:10
in a reactive context, it's a good trigger to just say, I should probably take that out and put it
4:14
into a reactive calculation. You'll get the benefits of using functions, like you're able to
4:20
sort of reason about this, or if you do type annotation, you can use type annotation on this
4:24
function. But you also get some major performance benefits to your application, because when you use
4:32
this function in the reactive graph, Shiny will automatically figure out the best way to call it
4:37
so that it won't be called too frequently, and yet everything will still stay up to date.
4:40
So that's basically the one takeaway from this whole session on reactivity is whenever you find
4:47
yourself using, like copying code, using code in two places, that's a sign you should put it into into a reactive calc.
4:53
If you do that, all of your Shiny applications will be very happy.