为什么无功值变化没有触发观察?

问题描述 投票:0回答:1

我的代码如下。

预期的行为是这样的:

  1. 用户单击操作按钮
    run_analysis
  2. 这会触发
    observeEvent
    input$run_analysis
    块,将无功值
    run_analysis_clicked
    更新为
    TRUE
  3. 此无功值的变化应该 then 触发要执行的
    observe
    块,从而更新
    mainPanelTabs
    选项卡集中选定的选项卡。

但事实并非如此。由于某种原因,在

observe
值更改后,
run_analysis_clicked
块不会被触发。

我尝试将其与最低限度可重复的样本配对。

library(shiny)

#### USER INTERFACE ####
ui <- fluidPage(
    titlePanel("Bootstrap Sample Size Simulator"),
    sidebarLayout(
        sidebarPanel(
            # Define the primary inputs needed to setup the sample size simulation
            fileInput("file_upload", "Upload a CSV file with sample data to use for sample size optimization:", accept = ".csv"),
            uiOutput("slider_output"),
            uiOutput("action_output")
        ),
        mainPanel(
            tabsetPanel(
                id = "mainPanelTabs",  # Add an ID for easier reference
                tabPanel("instructions", "Instructions content goes here."),
                tabPanel("data", "Data content goes here."),
                tabPanel("results", "Results content goes goes here.")
            )
        )
    )
)

#### SERVER ####
server <- function(input, output, session) {
    # Define reactive values that populate when the file is uploaded
    upload <- reactiveValues(
        isUploaded = FALSE, # flag signifying the file has been uploaded
        data = NULL, # empty placeholder for the data
        sample_max = NULL # initialize as empty
    )
    
    # Define reactive value that identifies when the run_analysis button has been clicked
    run_analysis_clicked <- reactive({
        FALSE # Flag is initially set to FALSE
    })
    
    # Define reactive value that updates the selected tab
    selectedTab <- reactiveVal("instructions")
    
    # Define function for creating the slider UI element for sample size limits selection
    slider_ui <- function() {
        if (upload$isUploaded) {
            sliderInput("sample_range",
                        label = "Range of Sample Sizes to simulate from the uploaded data:",
                        min = 2,
                        max = upload$sample_max,
                        step = 1,
                        value = c(2, upload$sample_max)
            )
        } else {
            NULL
        }
    }
    
    # Define function for creating the run analysis button
    action_ui <- function() {
        if (upload$isUploaded) {
            actionButton("run_analysis",
                         label = "Run the analysis"
            )
        } else {
            NULL
        }
    }
    
    # Update reactive values when file is uploaded
    observeEvent(input$file_upload, {
        upload$isUploaded <- TRUE  # update flag after file is uploaded
        upload$data <- read.csv(input$file_upload$datapath) # read the uploaded CSV file
        upload$sample_max <- nrow(upload$data) # update sample_max after file has been 
        print(paste("upload$sample_max:",upload$sample_max))
    })
    
    # Update reactive values when button is clicked
    observeEvent(input$run_analysis, {
                 run_analysis_clicked <- TRUE # update flag after button clicked
                 print(paste("run_analysis_clicked",run_analysis_clicked))
                 })
    
    # Update selected tab based on upload and button click events
    observe({
        print("observe triggered")
        print(paste("upload$isUploaded:",upload$isUploaded))
        print(paste("run_analysis_clicked:",run_analysis_clicked()))
        if (!upload$isUploaded) {
            selectedTab("instructions")
        } else if (run_analysis_clicked() == FALSE) {
            selectedTab("data")
        } else {
            selectedTab("results")
        }
        
        # Update the selected tab directly in the UI
        updateTabsetPanel(session, "mainPanelTabs", selected = selectedTab())
    })
    
    # Render the slider and action buttons conditionally upon file upload
    output$slider_output <- renderUI({
        slider_ui()
    })
    output$action_output <- renderUI({
        action_ui()
    })
}

#### APP ####
shinyApp(ui = ui, server = server)

这是控制台输出(添加了注释,解释了触发输出的操作):

Listening on http://xxxxxx
# App Initialized: 
[1] "observe triggered"
[1] "upload$isUploaded: FALSE"
[1] "run_analysis_clicked: FALSE"
# File Uploaded:
[1] "upload$sample_max: 15"
[1] "observe triggered"
[1] "upload$isUploaded: TRUE"
[1] "run_analysis_clicked: FALSE"
# Button Clicked:
[1] "run_analysis_clicked TRUE"

对于文件上传,我仅使用一个 CSV 文件,其中包含我在 Excel 中创建的 15 个随机数。它看起来像这样:

样本数据
0.590024857449706
0.0728674995484038
0.481874325987865
0.960001135837481
0.294927454278591
0.25254752567793
0.460322873384411
0.00237222444026342
0.169595016393134
0.444750644528156
0.033684417887163
0.973733565927954
0.917744500279373
0.264506821656346
0.998370147928976
r shiny shiny-reactivity
1个回答
1
投票

这里需要理解的一件重要的事情是

run_analysis_clicked <- reactive({
        FALSE # Flag is initially set to FALSE
    })

不定义反应值,它定义反应表达式。如果将变量定义为

reactive
,则无法在其反应环境之外更改其值。您可以想象,您在
reactive
上只有“读”权限,而在
reactiveVal
上您拥有“读”和“写”权限。

由于您将

reactive
定义为
FALSE
,因此应用程序内的任何地方都无法观察到此变量的变化。实现这一点的一种可能性是定义对
reactiveVal
的依赖,例如

rv <- reactiveValues(blnRunAnalysisClicked = TRUE)
run_analysis_clicked <- reactive({rv$blnRunAnalysisClicked})

但就您而言,我们可以跳过

reactive
部分并直接依赖
reactiveVal
,例如正如下面的例子(
upload$run_analysis_clicked
)所示,它可以工作。

library(shiny)

#### USER INTERFACE ####
ui <- fluidPage(
  titlePanel("Bootstrap Sample Size Simulator"),
  sidebarLayout(
    sidebarPanel(
      # Define the primary inputs needed to setup the sample size simulation
      fileInput("file_upload", "Upload a CSV file with sample data to use for sample size optimization:", accept = ".csv"),
      uiOutput("slider_output"),
      uiOutput("action_output")
    ),
    mainPanel(
      tabsetPanel(
        id = "mainPanelTabs",  # Add an ID for easier reference
        tabPanel("instructions", "Instructions content goes here."),
        tabPanel("data", "Data content goes here."),
        tabPanel("results", "Results content goes goes here.")
      )
    )
  )
)

#### SERVER ####
server <- function(input, output, session) {
  # Define reactive values that populate when the file is uploaded
  upload <- reactiveValues(
    isUploaded = FALSE, # flag signifying the file has been uploaded
    data = NULL, # empty placeholder for the data
    sample_max = NULL, # initialize as empty
    run_analysis_clicked = FALSE 
  )
  
  # Define reactive value that updates the selected tab
  selectedTab <- reactiveVal("instructions")
  
  # Define function for creating the slider UI element for sample size limits selection
  slider_ui <- function() {
    if (upload$isUploaded) {
      sliderInput("sample_range",
                  label = "Range of Sample Sizes to simulate from the uploaded data:",
                  min = 2,
                  max = upload$sample_max,
                  step = 1,
                  value = c(2, upload$sample_max)
      )
    } else {
      NULL
    }
  }
  
  # Define function for creating the run analysis button
  action_ui <- function() {
    if (upload$isUploaded) {
      actionButton("run_analysis",
                   label = "Run the analysis"
      )
    } else {
      NULL
    }
  }
  
  # Update reactive values when file is uploaded
  observeEvent(input$file_upload, {
    upload$isUploaded <- TRUE  # update flag after file is uploaded
    upload$data <- read.csv(input$file_upload$datapath) # read the uploaded CSV file
    upload$sample_max <- nrow(upload$data) # update sample_max after file has been 
    print(paste("upload$sample_max:",upload$sample_max))
  })
  
  # Update reactive values when button is clicked
  observeEvent(input$run_analysis, {
    upload$run_analysis_clicked <- TRUE # update flag after button clicked
    print(paste("run_analysis_clicked", upload$run_analysis_clicked))
  })
  
  # Update selected tab based on upload and button click events
  observe({
    print("observe triggered")
    print(paste("upload$isUploaded:",upload$isUploaded))
    print(paste("run_analysis_clicked:",upload$run_analysis_clicked))
    if (!upload$isUploaded) {
      selectedTab("instructions")
    } else if (upload$run_analysis_clicked == FALSE) {
      selectedTab("data")
    } else {
      selectedTab("results")
    }
    
    # Update the selected tab directly in the UI
    updateTabsetPanel(session, "mainPanelTabs", selected = selectedTab())
  })
  
  # Render the slider and action buttons conditionally upon file upload
  output$slider_output <- renderUI({
    slider_ui()
  })
  output$action_output <- renderUI({
    action_ui()
  })
}

#### APP ####
shinyApp(ui = ui, server = server)
© www.soinside.com 2019 - 2024. All rights reserved.