Shiny Reactivity
Examples of passing a list of reactives, reactiveValues list and reactiveValues to a shiny module. This helps explain reactivity when passing values to a shiny module. In each case we pass a value A
which triggers mod A
and value B
which triggers mod B
. The code below and output demonstrates which outputs in the shiny module are updated upon changing a value in the main app.
- Example 1 - list of reactives. Two reactives passed to shiny module in a list. When
value A
is updated onlymod A
updates. - Example 2 - ReactiveValues List. Two reactives passed to shiny module in a reactive list. The individual components are not reactive themselves but the list is. This means that when one list item is changed it triggers updates for each output that implements any member of the list. When
value A
is updated, bothmod A
andmod B
update. - Example 3 - ReactiveValues. Two reactiveValues passed to shiny module. When
value A
is updated onlymod A
updates.
Example 1 - List of Reactives
Pass two reactives (react_A
and react_B
) to a shiny module. react_A
is attached to a reactiveVal and initially set to A. react_B
is a reactive set to B. react_A
is then changed to C by changing the reactiveVal.
In this setup react_A
and react_B
are sent to the shiny module when it is called. react_A
is updated which triggers an update of the module.
Output to the console is:
1[1] "response from module A: A"
2[1] "response from module B: B"
3[1] "response from module A: C"
1## checking reactivity - reactive list vs list of reactives
2## list of reactives
3library(shiny)
4
5## module UI
6mod_UI <- function(id) {
7 ns <- NS(id)
8 tagList(
9 uiOutput(ns("modA")),
10 uiOutput(ns("modB"))
11 )
12}
13
14## module server
15mod <- function(id, inputvar) {
16 moduleServer(
17 id,
18 function(input, output, session) {
19 output$modA <- renderUI({
20 req(inputvar$A())
21 print(paste0("response from module A: ", inputvar$A()))
22 h3(paste0("response from module A: ", inputvar$A()))
23 })
24
25 output$modB <- renderUI({
26 req(inputvar$B())
27 print(paste0("response from module B: ", inputvar$B()))
28 h3(paste0("response from module B: ", inputvar$B()))
29 })
30 }
31 )
32}
33
34ui <- fluidPage(
35
36 mod_UI("shinymod")
37
38)
39
40server <- function(input, output, session) {
41
42 rv <- reactiveVal("A")
43
44 react_A <- reactive({
45 rv()
46 })
47
48 react_B <- reactive({
49 "B"
50 })
51
52 mod("shinymod", inputvar = list(A = reactive(react_A()), B = reactive(react_B())))
53
54 ## Update rv$A triggers refresh of modA in shiny module but not modB
55 observe({
56 rv("C")
57 })
58
59}
60
61shinyApp(ui, server)
Example 2 - ReactiveValues List
Pass a reactiveValue, rv$AB
containing a list of two members (A = A and B = B) to a shiny module. One member of rv$AB
is then changed so that rv$AB
contains A = C and B = B.
In this setup rv$AB
is sent to the shiny module when it is called. rv$AB
is updated which triggers an update of the module.
Output to the console is:
1[1] "response from module A: A"
2[1] "response from module B: B"
3[1] "response from module A: C"
4[1] "response from module B: B"
Here it is clear that updating the reactiveValue triggers two updates - one for the first list member (which changed) and one for the second (which did not). This is a highly inefficient way of passing data to a module.
1## checking reactivity - reactive list vs list of reactives
2## reactiveValue
3library(shiny)
4
5## module UI
6mod_UI <- function(id) {
7 ns <- NS(id)
8 tagList(
9 uiOutput(ns("modA")),
10 uiOutput(ns("modB"))
11 )
12}
13
14## module server
15mod <- function(id, inputvar) {
16 moduleServer(
17 id,
18 function(input, output, session) {
19
20 output$modA <- renderUI({
21 req(inputvar()$A)
22 print(paste0("response from module A: ", inputvar()$A))
23 h3(paste0("response from module A: ", inputvar()$A))
24 })
25
26 output$modB <- renderUI({
27 req(inputvar()$B)
28 print(paste0("response from module B: ", inputvar()$B))
29 h3(paste0("response from module B: ", inputvar()$B))
30 })
31
32 }
33 )
34}
35
36
37ui <- fluidPage(
38
39 mod_UI("shinymod")
40
41)
42
43server <- function(input, output, session) {
44
45 rv <- reactiveValues(
46 AB = list()
47 )
48
49 observe({
50 rv$AB <- list(A = "A", B = "B")
51 })
52
53 mod("shinymod", inputvar = reactive(rv$AB))
54
55 ## Update rv$AB triggers refresh of modA and modB in shiny module
56 observe({
57 rv$AB <- list(A = "C", B = "B")
58 })
59
60}
61
62shinyApp(ui, server)
Example 3 - ReactiveValues
Pass a set of reactiveValues, rv
containing two elements (A = A and B = B) to a shiny module. Change one element (A = C).
In this setup rv
is sent to the shiny module when it is called. rv
is updated which triggers an update of the module.
Output to the console is:
1[1] "response from module A: A"
2[1] "response from module B: B"
3[1] "response from module A: C"
1## checking reactivity - reactive list vs list of reactives
2## reactiveValues
3library(shiny)
4
5mod_UI <- function(id) {
6 ns <- NS(id)
7 tagList(
8 uiOutput(ns("modA")),
9 uiOutput(ns("modB"))
10 )
11}
12
13## module server
14mod <- function(id, inputvar) {
15 moduleServer(
16 id,
17 function(input, output, session) {
18
19 output$modA <- renderUI({
20 req(inputvar()$A)
21 print(paste0("response from module A: ", inputvar()$A))
22 h3(paste0("response from module A: ", inputvar()$A))
23 })
24
25 output$modB <- renderUI({
26 req(inputvar()$B)
27 print(paste0("response from module B: ", inputvar()$B))
28 h3(paste0("response from module B: ", inputvar()$B))
29 })
30
31 }
32 )
33}
34
35ui <- fluidPage(
36
37 mod_UI("shinymod")
38
39)
40
41server <- function(input, output, session) {
42
43 rv <- reactiveValues(
44 A = "A",
45 B = "B"
46 )
47
48 mod("shinymod", inputvar = reactive(rv))
49
50 ## Update rv$A triggers refresh of modA in shiny module
51 observe({
52 rv$A <- "C"
53 })
54
55 ## Update rv$B does not trigger refresh of modB in shiny module (no change to rv$B)
56 observe({
57 rv$B <- "B"
58 })
59
60}
61
62shinyApp(ui, server)