1
votes

I have a reactiveVal data.frame inside a shiny app that I'd like to sort. However, the attempt known from standard data.frames failed:

r <- reactiveVal(data.frame(val = c(1,3,2), name = c("Jim", "Anna", "Mouse")))
r(r()[order(r()$val, decreasing = TRUE), ])

Error in .getReactiveEnvironment()$currentContext() : Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)


A full example:

library(shiny)

ui <- fluidPage(mainPanel(textOutput("text")))

server <- function(input, output) {
  r <- reactiveVal(data.frame(val = c(1,3,2), name = c("Jim", "Anna", "Mouse")))
  # r(r()[order(r()$val, decreasing = TRUE), ])
  output$text <- renderText(
    paste0("The maximum value is ", r()$val[1],", scored by ", r()$name[1], 
           ". The second place goes to ", r()$name[2]," with a value of ", 
           r()$val[2]))
}

shinyApp(ui = ui, server = server)
1
does r()[order(r()$val, decreasing = TRUE), ] work? - Cettt
@Cettt No, it throws the same error, unless placed as supposed by Joris Chau's answer below. - symbolrush

1 Answers

1
votes

As the error message states:

(You tried to do something that can only be done from inside a reactive expression or observer.)

That is, the reassignment r(r()[order(r()$val, decreasing = TRUE), ]) has to happen inside e.g. an observe or observeEvent call. This makes sense, since r is defined as a reactive value, meaning that its input is expected to change in response to certain events (e.g. clicking an action button) and we should reorder the rows of the data.frame after each input change.

If the data.frame is static in the sense that it does not change in response to an event, it does not need to be defined as a reactive value with reactiveVal and we can reorder the rows of the data.frame outside a reactive expression or observer:

server <- function(input, output) {

r <- data.frame(val = c(1,3,2), name = c("Jim", "Anna", "Mouse"))
r <- r[order(r$val, decreasing = TRUE), ]     

 output$text <- renderText({

        paste0("The maximum value is ", r$val[1],", scored by ", r$name[1], 
            ". The second place goes to ", r$name[2]," with a value of ", 
            r$val[2])

      })

}

Instead of reordering r inside an observe or observeEvent call, we can also reorder the reactive value inside renderText, which also counts as a reactive expression/observer. (NB: in this case the reordered data.frame is not assigned back to the reactive value r).

server <- function(input, output) {

  r <- reactiveVal(data.frame(val = c(1,3,2), name = c("Jim", "Anna", "Mouse")))

  output$text <- renderText({

        r_ordered <- r()[order(r()$val, decreasing = TRUE), ]

        paste0("The maximum value is ", r_ordered$val[1],", scored by ", r_ordered$name[1], 
            ". The second place goes to ", r_ordered$name[2]," with a value of ", 
            r_ordered$val[2])

      })

}