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.


Talk Python's Mastodon Michael Kennedy's Mastodon