● R-bloggers
📅 10/03/2026 à 21:26
Sharing data across shiny modules, an update
👤 Colin Fay
🏷️ Tags :
pm
[This article was first published on Rtask, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here) Want to share your content on R-bloggers? click here if you have a blog, or here if you don't. You can read the original post in its original format on Rtask website by ThinkR here: Sharing data across shiny modules, an update Some people have recently been vocal about misuses of the "stratégie du petit r", a mechanism for sharing data across {shiny} modules that was detailed both in the Engineering Production-Grade Shiny Apps book and in an older post written in 2019 on this blog. And yes, if you’re wondering, I did feel old when I realized this blog post is almost 7 years old now I’m always happy to be proven wrong, to challenge the way I build software, and to become a better software engineer. But given that we weren’t contacted to discuss the ideas behind this strategy, I thought the moment was perfect to give y’all an update on the latest approaches I’ve been using to share data across {shiny} modules, along with some thoughts and comments on the "stratégie du petit r". Discovering {shiny} modules I’ve been building {shiny} apps for quite a while now. I’ve probably built more apps than I can remember, and for far longer than I dare to admit. One of the apps I’m most proud of is used by 1,000+ people in a large company, managing millions of euros every year. I’ve been working on this one for five years now. I can still remember the day Vincent sent us a message on Slack, sharing a video about {shiny} modules and how they would change the way we build apps. I was on a train ride back from one of the many R conferences I’ve attended (and spoken at) over the years. I think this might be in 2017, but I’m not really sure. And I’ll admit it: I had absolutely no idea what this video was about, or how it would fit into my current {shiny} apps. Being the nerd that I am, I watched this video a couple of times because I wanted to understand it and use it. Any time Vincent shows up and says something will change your coding style, you’d better listen and understand. It took me a bit of time, but after a couple of months, {shiny} modules were a core part of my development workflow, and the add_module() function from {golem} became one of my favorites: it has saved me five minutes of perilous copy-pasting every time I need a new module. That’s a significant amount of lifetime saved thanks to a simple function. But one of the more complex things with {shiny} modules is this: how do you share global state, data, and reactivity between them? How do I access the CSV read in mod_csv_reader from mod_data_visualisation? Let’s dive into this question. What is a {shiny} module Modules are functions I feel like {shiny} modules have been mistakenly presented as “reusable pieces of {shiny} code”. Well, they are, but 95% of the modules I’ve written in my career have been used only once. And that’s because most of the time, parts and pieces of an app are too specific to be reused anywhere else. So {shiny} modules are useful primarily because they address a scoping issue: via two functions, they let you define a small part of your app without having to worry about ID uniqueness across the whole application. Basically, they are building blocks: you start at the top level, then break things down into smaller and smaller pieces. {shiny} modules being functions means several things: They operate in an ecosystem of environments They are scoped, meaning what happens in them usually stays there unless you actively decide otherwise They can take inputs and generate outputs Good software engineering practice tells us: a function should take a set of inputs, do just one thing, and produce an output, and we plug these functions into one another like Russian dolls to build a larger workflow. So we might have, for example, one module that contains a tab of the app, which contains two cards, with one card being a module that contains a module with a fileInput to read a CSV. Let’s take a look at a simple application like this GPX Viewer, with the source code available at https://github.com/ThinkR-open/gpxviewer. This app follows a pretty common Shiny workflow: take a dataset, plot it, and summarize it. There are multiple ways to split this app into modules. This can be seen as splitting modules by “doing just one thing” (data configuration / data visualization): Another could be (upload / configure / plot / summarize): This too (check for example / upload / configure / download / plot / summarize): What I’m trying to show here is that “just one thing” can be relative in the context of a big app. Furthermore, and I think this is the biggest point: we need to strike a balance between perfect and practical. For example, I’m currently working for a client where the codebase (R code only) is just under 20,000 lines, and if you start from the top level, the deepest module in the stack is six levels down. Of cour
🔗 Lire l'article original
👁️ 3 lectures