I am writing a shiny app where the output should depend on the value of a variable which is calculated in a reactive expression in shiny. Instead of reproducing the actual app I believe I have recreated my problem with the following simple app:
ui.R file:
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Illustrating problem"),
sidebarPanel(
numericInput('id1', 'Numeric input, labeled id1', 0, min = 0, max = 100, step =5)
),
mainPanel(
h4('You entered'),
verbatimTextOutput("oid1"),
verbatimTextOutput("odic")
)
))
server.R file
library(shiny)
shinyServer(
function(input, output) {
output$oid1 <- renderPrint({input$id1})
x<-reactive({5*input$id1})
if (x()>50) output$oid2<-renderPrint({"You entered a number greater than 10"})
else output$oid2<-renderPrint({"You entered a number less than or equal to
10"})
}
)
If I run it like this then I get the error:
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.)
If I change the if statement to: if (x>50)
... then I get the error:
Error in x > 50 : comparison (6) is possible only for atomic and list types
When I change the if statement to: if (reactive({(x>50)}))
... then I get the error message:
Error in if (reactive({ : argument is not interpretable as logical
I'd greatly appreciate any help
A couple problems. The first and biggest problem is that you don't seem to understand how reactivity works. The error says "operation not allowed without an active reactive context" and that's the problem - you're accessing x()
inside the server function's main body but not within a reactive context. Any render*
function is a reactive context for example. So to solve this you simple have to move the if statement inside the renderPrint
.
The other small problem is that your output ids don't match (verbatimTextOutput("odic")
vs output$oid2
).
If you don't understand reactivity, I highly suggest you take half an hour to understand it better. This tutorial has a section on reactivity that can be helpful, or you can re-read the official shiny tutorial by RStudio.
Here's the code for your fixed app (I removed a bunch of useless UI elements)
library(shiny)
ui <- fluidPage(
numericInput('id1', 'Numeric input, labeled id1', 0, min = 0, max = 100, step=5),
verbatimTextOutput("oid1"),
verbatimTextOutput("oid2")
)
server <- function(input, output, session) {
output$oid1 <- renderPrint({input$id1})
x<-reactive({5*input$id1})
output$oid2<-renderPrint({
if (x()>50) {
"You entered a number greater than 10"
} else {
"You entered a number less than or equal to 10"
}
})
}
shinyApp(ui = ui, server = server)
Note that Shiny works based according to an event driven model - as do pretty much all graphically oriented UIs (and today that is the vast majority). It is not a new concept, has been around since the 80s at least, but it is more complicated than a programming something that follows a single flowchart - it does take some getting used to.
Anyway, in Shiny reactive
and output
andobserve
statements have to be at the top level, I don't think there are exceptions to this.
You probably want something like this:
library(shiny)
u <- shinyUI(pageWithSidebar(
headerPanel("Illustrating problem"),
sidebarPanel(
numericInput('id1', 'Numeric input, labeled id1', 0, min = 0, max = 100, step =5)
),
mainPanel(
h4('You entered'),
verbatimTextOutput("oid1"),
verbatimTextOutput("oid2")
)
))
s <- shinyServer(function(input, output) {
output$oid1 <- renderPrint({input$id1})
x<-reactive({5*input$id1})
output$oid2<-renderPrint({
if (x()>50){
"You entered a number greater than 10"
} else {
"You entered a number less than or equal to 10"
}
}
)
}
)
shinyApp(ui = u, server = s)
Yielding:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With