Eric Green
Eric Green

Reputation: 7735

shiny reactive object not found

I think I'm missing something with respect to reactives in my Shiny app. Here's a MRE that shows my problem printing y.

library(shiny)

ui <- fluidPage(
   titlePanel("Test"),
   textAreaInput("text", "Text", "", width = "400px"),
   verbatimTextOutput("text"),
   actionButton("do", "Run"),
   textOutput("result")
   )

server <- function(input, output) {
  observeEvent(input$do, {
  y <- reactive({
    x <- ""
    t <- 1
    while (t < 5) {
      x <- paste(input$text, x, sep=",")
      t <- t + 1
    }
  })
  })
  output$result <- renderPrint({y})
}

shinyApp(ui = ui, server = server)

Upvotes: 1

Views: 2886

Answers (2)

tbradley
tbradley

Reputation: 2290

You shouldn't put a reactive value inside of an observeEvent or observe call. In fact, it has been advised by Joe Cheng to never nest either observe or reactive functions within either themselves or the other. They are separate things used for different purposes. Since you want the reactive y to be created based on when input$do is clicked, you should use eventReactive:

server <- function(input, output) {
  y <- eventReactive(input$do, {
    x <- ""
    t <- 1
    while (t < 5) {
      x <- paste(input$text, x, sep=",")
      t <- t + 1
    }
    return(x)
  })

  output$result <- renderText({y()})
}

I changed renderPrint() to renderText() so that it displays your desired output. Also, since y is a reactive, you need to add y() after it in the renderText() call. I also added return(x) to the eventReactive call, otherwise t would be the value returned.

Upvotes: 5

AdagioMolto
AdagioMolto

Reputation: 192

I the problem is that your call to reactive() does not return anything. Wrapping an expression inside reactive assigns the return value of the expression to a variable each time a reactive value inside the expression is changed. Reactive values are usually all input$... variables, and those that you store in reactiveValues() objects.

If I get you right you want to change and print y every time the "run" button is hit. Save this to a reactiveValue() collection (similarly accessible like a list), and then put this inside your renderPrint function.

From your code I reckon that you want y to be the value of x after the while loop.

library(shiny)

ui <- fluidPage(
  titlePanel("Test"),
  textAreaInput("text", "Text", "", width = "400px"),
  verbatimTextOutput("text"),
  actionButton("do", "Run"),
  textOutput("result")
)

server <- function(input, output) {
  values <- reactiveValues()
  observeEvent(input$do, {
    x <- ""
    t <- 1
    while (t < 5) {
      x <- paste(input$text, x, sep=",")
      t <- t + 1
    }
    values$y <- x
  })
  output$result <- renderPrint({values$y})
}

shinyApp(ui = ui, server = server)

Upvotes: 1

Related Questions