There are very rare use cases to have observes creates renderfunction hooks; the typical case should be that renderfunctions are simply defined at the top level, and your code provides the inputs, and it works. Also reusable data elements, like the currently active name associated with the selected mode, can become reactive elements in their own right, so you can reuse them wherever they are needed reducing code duplications and gaining the benefits of modularity.
Perhaps you have usecase where update* on your controls has to be frequent but in this example at least its superflous, as the update* needs to only be set one time, so I cleaned up that up also here.
library(shiny)
ui <- fluidPage(
selectInput("mode","Mode", choices = "", multiple = F, width = "250px"),
h5(textOutput("text")),
)
server <- function(input, output, session) {
modes <- c("A" = 1, "B" = 2, "C" = 3)
#in this example its only needed to set the input$mode exactly once ...
updateSelectInput(session = session, inputId = "mode", choices = modes, selected = 1)
active_mode_name <- reactive({
names(modes)[which(modes == req(input$mode))]
})
output$text <- renderText({paste(" Mode = ", active_mode_name())})
}
shinyApp(ui = ui, server = server)