Home > Net >  How to move code from render function to a more general reactive function in r shiny?
How to move code from render function to a more general reactive function in r shiny?

Time:08-05

In the below demo code (used in one of my earlier questions), I'm trying to move the processing code inside output[["choices2"]] <- renderTable({...}) function from renderTable() and into a separate reactive() function. You can see my attempt commented-out, but I got Error in get_quosure(x, env, quoted) : object 'dat' not found when I tried running this.

What am I doing wrong?

Btw, I'm trying to do this so I can use dat in other places. Maybe there's another way to extract dat for use elsewhere without taking it out of output[["choices2"]] <- renderTable({...})?

Demo code:

library(shiny)

data <- 
  data.frame(
    ID = c(1,1,1,2,2,2),
    Period = c(1, 2, 3, 1, 2, 3),
    Values = c(5, 10, 15, 0, 2, 4)
  )

ui <- fluidPage(
  
  h5(strong("Base data frame:")), 
  tableOutput("data"),
  radioButtons(inputId = "showData",
               label = h5(strong("Show from original dataframe:")),
               choiceNames = c('All','First 2 rows'),
               choiceValues = c('All','Rows'),
               selected = 'All',
               inline = TRUE
              ),
  h5(strong("Reactive results:")), 
  tableOutput("choices1"),
  h5(strong("Mirror results x 2:")), 
  tableOutput("choices2")
  )

server <- function(input, output, session) {
 
  output$data <- renderTable(data)
  
  rv <- reactiveValues(choices1=c()) 
  observeEvent(input$showData,{if(input$showData=='Rows'){rv$choices1 <- data[1:2,]} else {rv$choices1<-data}})
  
  output[["choices1"]] <- renderTable({rv$choices1})

  # dat <- reactive(
  #   dat <- rv$choices1,
  #   dat[, 3] <- 2 * dat[, 3],
  #   dat
  # )
  
  output[["choices2"]] <- renderTable({
    # dat()
    # Comment-out the next 3 lines and un-comment the commented to try running my creation of reactive "dat"
    dat <- rv$choices1
    dat[, 3] <- 2 * dat[, 3]
    dat
  })
  
}

shinyApp(ui, server)

CodePudding user response:

The reason why your code wasn't working is due to 2 things:

  • You need to put {} after reactive --> reactive({ code })
  • You cannot use commas to separate your lines of code.

BEFORE:

dat <- reactive(
    dat <- rv$choices1,
    dat[, 3] <- 2 * dat[, 3],
    dat
)

AFTER:

dat <- reactive({
    dat <- rv$choices1
    dat[, 3] <- 2 * dat[, 3]
    dat
  })

Having changed those 2 things, your code works perfectly and dat() can be used in other places apart from renderTable.

Btw, just a note, it is the first time that I see that someone uses output[["choices2"]], I would write output$choices2. However, as I see, it works, so... you could use either.

Complete code:

library(shiny)

data <- 
  data.frame(
    ID = c(1,1,1,2,2,2),
    Period = c(1, 2, 3, 1, 2, 3),
    Values = c(5, 10, 15, 0, 2, 4)
  )

ui <- fluidPage(
  
  h5(strong("Base data frame:")), 
  tableOutput("data"),
  radioButtons(inputId = "showData",
               label = h5(strong("Show from original dataframe:")),
               choiceNames = c('All','First 2 rows'),
               choiceValues = c('All','Rows'),
               selected = 'All',
               inline = TRUE
  ),
  h5(strong("Reactive results:")), 
  tableOutput("choices1"),
  h5(strong("Mirror results x 2:")), 
  tableOutput("choices2")
)

server <- function(input, output, session) {
  
  output$data <- renderTable(data)
  
  rv <- reactiveValues(choices1=c()) 
  observeEvent(input$showData,{if(input$showData=='Rows'){rv$choices1 <- data[1:2,]} else {rv$choices1<-data}})
  
  output[["choices1"]] <- renderTable({rv$choices1})
  
  dat <- reactive({
    dat <- rv$choices1
    dat[, 3] <- 2 * dat[, 3]
    dat
  })

  output[["choices2"]] <- renderTable({
     dat()
    # Comment-out the next 3 lines and un-comment the commented to try running my creation of reactive "dat"
    # dat <- rv$choices1
    # dat[, 3] <- 2 * dat[, 3]
    # dat
  })
  
}

shinyApp(ui, server)
  • Related