【问题标题】:Dynamic `updateTabItems()` in Shiny get executed later than it is supposed toShiny 中的动态 `updateTabItems()` 执行得比预期的要晚
【发布时间】:2021-06-16 07:42:55
【问题描述】:

在以下示例中,我在“Tab1”中使用actionLink() 将显示切换到“Tab2”,然后将textInput() 中的文本更新为“iris”,最后单击按钮以显示实际数据。

由于未知原因,此开关在Sys.sleep() 之后执行。这会导致不希望的行为,因为shinyjs::click() 例如尝试触发一个尚不存在的按钮,因此不显示“虹膜”表。我本来希望首先切换选项卡,然后获取Sys.sleep()

有人可以向我解释一下为什么 Shiny 会有这样的行为以及如何执行预期的行为吗?

library(shiny)
library(shinydashboard)
library(shinydashboardPlus) # shinydashboardPlus_0.7.5 // devtools::install_version("shinydashboardPlus", version = "0.7.5", repos = "http://cran.us.r-project.org")
library(shinyjs)

available_data_sets <- c("mtcars", "iris")

ui_welcome <- fluidPage(actionLink(inputId = "switch_tab", label = "Switch tab, update text with 'iris' & click button", icon = icon("hand-point-right")))

ui_search <- fluidPage(
  textInput(inputId = "dataset_name", label = "Select data set", value = ""),
  actionButton(inputId = "display_tab", label = "Display selected set"),
  br(),
  tableOutput('table'))

ui <- dashboardPagePlus(
  collapse_sidebar = TRUE,
  title = "Minimal",
  header = dashboardHeaderPlus(
    title = "Test",
    enable_rightsidebar = FALSE,
    rightSidebarIcon = "gears",
    fixed = FALSE),
  sidebar = dashboardSidebar(
    sidebarMenu(
      id = "left_sidebar",
      menuItem("Tab1", tabName = "tab1", icon = icon("home")),
      menuItem("Tab2", tabName = "tab2", icon = icon("search")))
  ),
  
  body = dashboardBody(
    useShinyjs(),
    tabItems(tabItem(tabName = "tab1", ui_welcome),
             tabItem(tabName = "tab2", ui_search)))
)

server <- function(input, output, session) {
  
  # RENDER DATA
  observeEvent(input$display_tab, {
    print("Within observeEvent 'display_tab'")
    selected <- input$dataset_name
    print(paste0("Value of 'input$dataset_name' received: ", selected))
    if(!isTruthy(selected)) return(NULL)
    if(!selected %in% available_data_sets) return(NULL)
    
    output$table <- renderTable(if(selected == "iris") iris else mtcars)
  })
  
  # SWITCH TAB & TRIGGER BTN
  observeEvent(input$switch_tab, {
    print("Within observeEvent 'switch_tab'")
    print("updateTabItems"); updateTabItems(session, inputId = "left_sidebar", selected = "tab2")
    print("updateTextInput 1"); updateTextInput(inputId = "dataset_name", value = "")
    print("updateTextInput 2"); updateTextInput(inputId = "dataset_name", value = "iris")
    print("Sys.sleep"); Sys.sleep(3)
    print("shinyjs::click"); shinyjs::click(id = "display_tab")
  })
}

shinyApp(ui, server)

【问题讨论】:

    标签: r shiny shiny-reactivity


    【解决方案1】:

    闪亮的反应是基于对单个事件的反应。您基本上是在尝试针对单个事件执行两个操作(重新配置界面然后对其进行操作)。它不起作用,因为重新配置实际上是在反应代码之间完成的。您正试图通过等待使用 Sys.sleep 函数来规避此问题。这只会暂停整个应用程序,它会像什么都没发生一样唤醒。尝试延长睡眠时间,您会注意到 UI 将无响应。

    解决方案是将代码重构为以数据为中心而非以用户为中心。您想要的是能够以两种不同的方式选择和显示数据集。一个“自动”通过单击链接,另一个通过提供数据集名称并单击按钮手动。

    在这里,我为数据集添加了一些内容,它能够在更改时重新显示,并提供两种设置状态的方法。

    server <- function(input, output, session) {
      # reactive value to store selected dataset
      state <- reactiveValues(selected=NULL)
    
      # AUTO RENDER DATA on selected dataset change
      output$table <- renderTable({
        if(!is.null(state$selected)) {
          if(state$selected == "iris") iris else mtcars
        }
      })
      
      # manual select dataset
      # already on tab so no need to switch
      observeEvent(input$display_tab, {
        if(!isTruthy(input$dataset_name) || !(input$dataset_name %in% available_data_sets)) {
          state$selected <- NULL
        } else {
          state$selected <- input$dataset_name
        }
      })
      
      # automatic selection through actionlink
      # select dataset and switch tab
      observeEvent(input$switch_tab, {
        state$selected <- "iris"
        updateTabItems(session, inputId = "left_sidebar", selected = "tab2")
      })
    }
    

    【讨论】:

    • Sys.sleep 只是在这里显示控制台之前/之后发生的事情,否则一切看起来都很快,我们无法弄清楚到底发生了什么。
    • 对不起,我不太理解你的例子。你能适应我的 MRE 吗?
    • 通过重构逻辑和删除延迟处理更新了我的答案
    猜你喜欢
    • 2013-12-19
    • 2018-12-04
    • 2016-01-23
    • 2021-12-19
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多