如何在Shiny应用中阻止未认证前渲染主面板与侧边栏?
解决Shiny应用认证前UI组件短暂显示的问题
问题背景
开发了一个带用户名/密码认证的Shiny应用,当前代码在用户登录前,sidebar和mainPanel会短暂显示后才被隐藏,需要实现认证完成前完全阻止这两个组件渲染(或一开始就隐藏,避免闪烁)。
原代码如下:
server <- function(input, output) { options(shiny.maxRequestSize=100*1024^2) library(V8) library(shinyjs) hide("sidebar") hide("mainPanel") credentials <- data.frame(username = c("user1", "user2"), password = c("password1", "password2"), stringsAsFactors = FALSE) observeEvent(input$login, { # Check if the entered credentials match the stored credentials user_data <- credentials[credentials$username == input$username & credentials$password == input$password,] if (nrow(user_data) > 0) { # Show the app UI and hide the login inputs hide("username") hide("password") hide("login") show("sidebar") show("mainPanel") } else { # Show an error message if the credentials are incorrect shinyjs::alert("Incorrect username or password. Please try again.") } }) } library(V8) library(shinyjs) ui <- fluidPage( useShinyjs(), textInput("username", "Username"), passwordInput("password", "Password"), actionButton("login", "Log in"), sidebarLayout( # Inputs: Select variables to plot div(id="sidebar",sidebarPanel( dateInput( inputId = "corte", label = "Data as of:", value = NULL, min = NULL, max = NULL, format = "dd-mm-yyyy", startview = "month", weekstart = 0, language = "en", width = NULL, autoclose = TRUE, datesdisabled = NULL, daysofweekdisabled = NULL ))), # Output: Show scatterplot div(id = "mainPanel",mainPanel( selectInput( inputId = "reporte", label = "Report", choices = c("A", "B"), selected = NULL, multiple = FALSE, selectize = TRUE, width = NULL, size = NULL ) ) ) ) ) shinyApp(ui, server)
问题原因
当前代码中hide("sidebar")和hide("mainPanel")是在server端启动后执行,而UI组件会先于server端的隐藏命令完成渲染,所以会出现短暂显示的闪烁现象。
解决方案
直接在UI层将sidebar和mainPanel设置为初始隐藏状态,无需等待server端命令。可以使用shinyjs::hidden()函数包裹对应的div,这样组件从一开始就处于隐藏状态,不会出现闪烁。
修改后的完整代码:
server <- function(input, output) { options(shiny.maxRequestSize=100*1024^2) library(V8) library(shinyjs) credentials <- data.frame(username = c("user1", "user2"), password = c("password1", "password2"), stringsAsFactors = FALSE) observeEvent(input$login, { # Check if the entered credentials match the stored credentials user_data <- credentials[credentials$username == input$username & credentials$password == input$password,] if (nrow(user_data) > 0) { # Show the app UI and hide the login inputs hide("username") hide("password") hide("login") show("sidebar") show("mainPanel") } else { # Show an error message if the credentials are incorrect shinyjs::alert("Incorrect username or password. Please try again.") } }) } library(V8) library(shinyjs) ui <- fluidPage( useShinyjs(), textInput("username", "Username"), passwordInput("password", "Password"), actionButton("login", "Log in"), sidebarLayout( # Inputs: Select variables to plot shinyjs::hidden(div(id="sidebar",sidebarPanel( dateInput( inputId = "corte", label = "Data as of:", value = NULL, min = NULL, max = NULL, format = "dd-mm-yyyy", startview = "month", weekstart = 0, language = "en", width = NULL, autoclose = TRUE, datesdisabled = NULL, daysofweekdisabled = NULL )))), # Output: Show scatterplot shinyjs::hidden(div(id = "mainPanel",mainPanel( selectInput( inputId = "reporte", label = "Report", choices = c("A", "B"), selected = NULL, multiple = FALSE, selectize = TRUE, width = NULL, size = NULL ) ) )) ) ) shinyApp(ui, server)
说明
- 去掉了server端初始的
hide("sidebar")和hide("mainPanel"),因为UI层已经设置为隐藏 - 用
shinyjs::hidden()包裹sidebar和mainPanel的div,确保组件从页面加载时就处于隐藏状态,彻底解决闪烁问题 - 登录逻辑保持不变,验证通过后依然用
show()方法显示这两个组件
内容的提问来源于stack exchange,提问作者Ekapunk
相关产品推荐
相关产品推荐

