3MW (Reactive expressions in R-Shiny)

Guten Tag!

Many greetings from Munich, Germany. Today we are talking about reactive expressions. In Shiny, that’s a huge concept that helps to save and modify values as needed. But before I show you how they work, let me throw in my regular announcements.

Data cleaning masterclass

It is said that data cleaning is 90% of all the data work. And since this is such a huge & important topic, I’m teaching you everything you need to succeed at data cleaning. You can check out the huge curriculum in my latest announcement.

And the good news is that a pre-sale on the Part 1 of the course will be released this month. If you want to master data cleaning, you can still sign up for detailed infos and promo codes via my course newsletter.

Quarto dashboards

One of the newest features of Quarto is the ability to easily create static dashboards. They are not as flexible as full-fledged Shiny apps but they make it easy to display key data. You can watch my newest YT tutorial to find out how that works:

As always, all code that you see here can be found on Github.

A simple app first

Let’s say that you have a data set that is supposed to be filtered via user inputs. As we’ve learned in the last two weeks, we can use input$thing to get the value of the input and then combine that with filter(). For that, we need some inputs and outputs in our UI of course.

Notice that I’ve used

  • bslib::layout_column_wrap() to place things next to each other, and

  • the {DT} packages to create a table output.

Now, imagine that you want to use the filtered data set in both the plot and in the table output. You might be tempted to repeat the same calculations multiple times like this:

Here’s what that will give us.

Avoid code repetition

Right now, our code is quite repetitive. We have the same code twice in our server function. And not only is that tedious to write, it makes our code also inefficient. If our data is large, it might take the double amount of time to filter the data set twice.

And this is where reactive expressions come in. You can wrap the code that you want to reuse into a reactive expression. The easiest way to do that is the reactive() function.

And then, instead of the repetitive input code, you can use the variable name of the reactive. But there’s one thing you have to watch out for: You will have to call the reactive like a function with ().

And with that, we have a much cleaner and more efficient code for the same app. And as for the weird call using (): You have to think about a reactive as a function that checks what the current value of the reactive is and gives you back that value.

Of course, it’s super easy to forget the parantheses. And if you do, you will get an error messages that can be different depending on where you use the reactive. So if you get a weird error message, make sure that you actually use the parentheses.

reactiveVal() vs reactive()

There are other ways to create reactive values. For example, there’s also reactiveVal(). This function lets you assign values more manually.

You see, with reactive() the value is calculated automatically and only automatically. You cannot set the value yourself. But with reactiveVal() you can. This is helpful when you need more control over the value of the reactive.

To rewrite our previous server with reactiveVal() you have to get used to the syntax of that function. You see, you can set and update the value of the reactive by calling the reactive again and then putting the new value inside the parentheses.

So that’s how you set a reactiveVal() in principle. Unfortunately, this app will not work right now. You will get an error that says that you can only do this in a reactive consumer.

That’s because to access things like input$species you need do it in an observer. Broadly speaking, an observer checks for changes in the UI and if you don’t have that, you cannot access the inputs. So that’s why there is the observer function observe() that you can use to wrap your code in.

But this also requires you to

  • define the reactiveVal() outside the observe() code, and

  • update the reactiveVal() inside of observe().

With that you have a working app that uses reactiveVal(). And as you may have noticed, reactiveVal() is a bit more manual than reactive(). But it gives you the flexibility to set and update the value of the reactive as you need it from anywhere in the code.

Using ReactiveValues()

Finally, if you dislike the syntax of reactiveVal() (that requires using updating inside of the parantheses), you can always use the reactiveValues() function. It works pretty much the same, but the syntax is more like a list which can be quite convenient.

Nice, we have covered three ways of using reactive expressions. As always, I hope you enjoyed this newsletter. Next week, we’ll talk about dynamic UIs. And if you have any questions, don’t hesitate to reply to this mail or contact me on LinkedIn.

See you next week,
Albert 👋

Enjoyed this newsletter? Here are other ways I can help you:

Join the conversation

or to participate.