Search code examples
rshiny

How to get a warning on "shiny app will not work if the same output is used twice"


This is an old Shiny issue: shiny app will not work if the same "output" is used two times in Ui.R

A simple example :

library(shiny)
## app.R ##
server <- function(input, output) {
  output$distPlot <- renderPlot({
    hist(rnorm(input$obs), col = 'darkgray', border = 'white')
  })
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      sliderInput("obs", "Number of observations:", min = 10, max = 500, value = 100)
    ),
    mainPanel(plotOutput("distPlot")
              # If the next line is commented out, histogram appears correctly
              ,plotOutput("distPlot")
              )
  )
)

shinyApp(ui = ui, server = server)

This doesn't work because :

Shiny doesn't support multiple outputs with the same name. This code would generate HTML where two elements have the same ID, which is invalid HTML. See this or this.

The result looks fine, but isn't what is expected (no histogram shown) :
enter image description here

The ShinyApp seems to be working normally :

Listening on http ://127.0.0.1:7081

Although I know this issue, I have already been tricked a few times in complex UIs, and I was wondering if there was a way to output an automatic warning in the console on this?
For example :

Warning message: Output 'distPlot' is used twice in UI - this is not supported and might lead to unexpected results

Thanks for sharing your solutions on this issue!

#EDIT : This has been solved from Shiny 1.8.1 on.
Just use shiny::devmode(TRUE)
Thanks @ismirsehregal for the hint

enter image description here


Solution

  • I think that it may be quite some task to print it out to the R console. But if you open your app and go to the JS console you should see an error message:

    Duplicate


    Feedback as requested (here in the answer to allow for formatting purposes):

    Your code covers basic cases, but there are some edge cases which you may be overlooking (this list does not claim to be exhaustive):

    1. If the name of the output element is in the next line, your code will not detect it.
    2. If the name of the element is not a string but in a variable it won't work either.

    (and this are just 2 cases I can quickly think of - and they are not completely unrealistic to be honest)

    Overall, I think it will be quite some work to cover all cases, while a quick look into the JS console reveals all you need, just in a different environment. IMHO completeness beats convenience.

    outname <- "distPlot"
    ui <- fluidPage(
       sidebarLayout(
          sidebarPanel(
             sliderInput("obs", "Number of observations:", min = 10, max = 500, value = 100)
          ),
          mainPanel(plotOutput("distPlot"),
                    plotOutput(
                       "distPlot" # not covered b/c in other line
                    ),
                    plotOutput(outname) # not covered b/c in variable
          )
       )
    )