Suggestions needed: What is the best way to use some inputs/outputs from one submodule in other submodules? #1105
Replies: 1 comment 1 reply
-
That's a really good question, I'll try to give some (limited) advice from my (limited) experience but more proficient users could answer this probably in much more detail. Your concerns about the "stratégie du petit r" approach may be sometimes valid. "petit r" or kitchen skink approaches are useful for "loose" global variables, as in your example, that don't warrant a fully-fledged R6 class (see below) and it's fine to pass around the reactive values from module to module. In terms of complexity it's probably ok to just to use it and see if you want to refactor it in your suggested style later (of course good style is to think about the reactive flow of your App before writing it, and make a reasonable draft of the global vars you want to pass around). There other are related approaches that help you in structuring you App if it really gets large and complicated, but since you are not using the submodule/module structure often maybe passing around reactive values is just fine…. Here are the alternatives I am aware of R6For a deeper dive into using R6 in Shiny, you can refer to the following resources: In short, you can add the R6 object as the last argument to every related module, providing direct access to necessary data stored inside it without navigating trough a web of reactive values (always thinking about which of the reactive values you'd want to pass). While "stratégie du petit r" is straightforward and effective for many use-cases to pass around values, R6 provides additional structure and encapsulation of whatever you decide to pass around; so if that thing is something complicated, and you end up defining functions for the petit-r variables to operate on them I'd consider using R6 classes directly. Advantages and Use-Cases
In summary, in my practice, I've found that R6's reference semantics offer a different way to manage state in Shiny apps quite beneficial. When an R6 object is passed to a module server, it's referred to directly, allowing for in-place modification and it makes it easy to look up in the class definition what you can do with this thing you are passing around (helps to reduce the cognitive burden in larger apps imho). Pseudo modulesYou may also be interested in a feature request currently open. This proposes the concept of "pseudo-modules" which are are rougly modules that share the same namespace as their parent module. This approach aims to simplify data passing between nested modules making the code more straightforward and less reliant on global variables or Comparing the usefullness of R6 style to pseudo modules is really depending on the context of the application. It’s probably the case that you can make it work either way, so what you choose might be a matter of style too. |
Beta Was this translation helpful? Give feedback.
-
When I develop my Shiny app, I basically go with the stratégie du petit r approach, meaning I use a
global reactiveValues
to pass data between different modules.source: Communication between modules and its whims
However, I do have some questions regarding how to facilitate communication between submodules in my Shiny app.
The submodule in my shiny app is defined as an
R function
with anUI
. It does not appear in the main app UI and server.While I could certainly apply the
stratégie du petit r
approach for submodule communication. I'm concerned that managing the app could become overly complex if I accumulate too many global variables in the list. There are situations where I only need to share specific inputs or outputs from one submodule with another module or submodule. These inputs and outputs don't warrant being designated as 'global variables' within my app.I think the idea of minimizing
main app global variables
in Shiny app and focusing on passing only the necessary data asmain app global variables
between modules can help improve the maintainability of the code and make it more organized.My ideas are:
Main App Global Variables: Only set the data that are important to run my app as
main app global variables
in the main app.Submodule Communication: For submodule communication, export reactive values or list within a submodule that contain the specific input/output data needed for other submodule/module operation.
Do you think this is a good approach or should I stick to the stratégie du petit r approach?
My another question is in many cases, submodules are actually used only once in my app, is it still worthwhole to write them as a submodule or only integrate them as a part of a module?
Below is a minimal example in which I export reactive values as a list within a submodule (instead of setting them as main app global variables in the main app server) in order to be used in another module. I think this is a bit easier to main than setting then as
main app global variables
. But I don't know the disadvantage of this approach.Thanks a lot for your suggestions.
Yonghui Dong
Beta Was this translation helpful? Give feedback.
All reactions