shinycssloaders包withSpinner首次点击失效问题求助
Shiny应用withSpinner首次点击加载异常修复方案
问题描述
使用shinycssloaders的withSpinner包裹多输出并通过fluidRow/column排版时,首次点击actionButton加载spinner会立即消失,后续点击则正常显示,需修复该问题并保留双列同行布局。
问题原因
- 原代码中
conditionalPanel的style = "display: none;"导致uiOutput("gather")初始状态被隐藏,withSpinner无法正确监听其渲染状态。 renderUI仅生成输出容器,未等待耗时的text2渲染完成,导致spinner在容器生成后提前消失。
修复方案
方案1:针对耗时输出单独添加Spinner(推荐)
仅在存在延迟的textOutput上包裹withSpinner,精准控制加载状态,同时简化UI结构:
library(shiny) library(shinycssloaders) ui <- fluidPage( textInput("text", "输入内容"), actionButton(inputId = "go", "执行"), # 直接使用uiOutput,移除多余的conditionalPanel样式 uiOutput("gather") ) server <- function(input, output) { val <- eventReactive(input$go, {input$text}) output$text1 <- renderText({ paste("1/", val()) }) output$text2 <- renderText({ Sys.sleep(4) paste("2/", val()) }) # 用req()替代conditionalPanel控制显示逻辑,直接渲染双列布局 output$gather <- renderUI({ req(input$go > 0) fluidRow( column(textOutput("text1"), width = 6), # 仅在耗时的text2上包裹withSpinner column(withSpinner(textOutput("text2"), type = 3), width = 6) ) }) } shinyApp(ui = ui, server = server)
方案2:让整体布局依赖耗时输出完成
通过req(output$text2)强制renderUI等待耗时输出完成后再渲染,确保withSpinner覆盖整个加载过程:
library(shiny) library(shinycssloaders) ui <- fluidPage( textInput("text", "输入内容"), actionButton(inputId = "go", "执行"), # 用withSpinner包裹整个uiOutput withSpinner(uiOutput("gather"), type = 3) ) server <- function(input, output) { val <- eventReactive(input$go, {input$text}) output$text1 <- renderText({ paste("1/", val()) }) output$text2 <- renderText({ Sys.sleep(4) paste("2/", val()) }) output$gather <- renderUI({ req(input$go > 0) # 强制依赖text2的输出,确保等待其渲染完成 req(output$text2) fluidRow( column(textOutput("text1"), width = 6), column(textOutput("text2"), width = 6) ) }) } shinyApp(ui = ui, server = server)
修改说明
- 移除
conditionalPanel的display: none样式,避免干扰withSpinner的状态监听。 - 使用
req(input$go > 0)替代conditionalPanel控制布局显示逻辑,代码更简洁。 - 方案1针对耗时输出单独设置Spinner,更符合实际加载场景;方案2让整个布局等待耗时任务完成,适合需要整体加载提示的场景。
内容的提问来源于stack exchange,提问作者thibaut.Ch
相关产品推荐
相关产品推荐

