You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny应用eventReactive使用后input$param不更新问题求助

问题描述

我正在用Shiny开发一款基于用户选择输入生成报表的应用,报表通过点击“Generar reporte”按钮生成,包含三类输入:

  • input_type:SelectInput,用于选择报表类型,选项为“Global”和“Por instituciones”;
  • param:仅当input_type为“Por instituciones”时显示的SelectInput;
  • date:用于定义报表日期的SelectInput。

异常流程

按以下操作时,param的选择不再生效,input$param始终为生成Global报表前的最后选中值:

  1. 选择input_type为“Global”;
  2. 点击“Generar reporte”生成报表;
  3. 切换input_type为“Por instituciones”;
  4. 点击“Generar reporte”生成报表。

现有代码

library(shiny)
library(DT)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      titlePanel("Repotería seguimiento PEIPRDCI"),
      selectInput("input_type", "Tipo reporte",
                  c("Global", "Por instituciones")), 
      uiOutput("ui"), 
      selectInput("date", "Seleccione la fecha:", 
                  choices = c("2023-01-01", "2023-02-01")), 
      actionButton("generate", "Generar reporte"), 
      downloadButton('downloadReport', "Descargar")
      
    ),
    
    mainPanel(
 
      htmlOutput("report")
      
    )
  )
)


server <- function(input, output) {

  output$ui <-  renderUI({
      if (input$input_type == "Por instituciones") {
                selectInput("param", "Seleccione la institución:", 
                            choices = c("BDE", "DIGERCIC"))
    } 
  })


  
  a <-  eventReactive(input$generate, {
    
    if(input$input_type == "Por instituciones")  {
      
      print(input$param)
      rmarkdown::render("C:/Users/santy/Documents/test5.Rmd",
                        params = list(institucion = input$param,
                                      fecha = input$date))
      
      includeHTML("C:/Users/santy/Documents/test5.html")

    } else {
      
      print(input$param)
      rmarkdown::render("C:/Users/santy/Documents/Reporte_seguimiento110523.Rmd",
                        params = list(fecha = input$date))
      includeHTML("C:/Users/santy/Documents/Reporte_seguimiento110523.html")
    }
  })

  output$report <-  renderUI({
    
a()
    
  })
  

  output$downloadReport <- downloadHandler(
    filename = function() {
      paste('my-report', sep = '.', 'html')
    },
    
    content = function(file) {
      src <- normalizePath('C:/Users/santy/Documents/test5.Rmd')
      
      # temporarily switch to the temp dir, in case you do not have write
      # permission to the current working directory
      owd <- setwd(tempdir())
      on.exit(setwd(owd))
      file.copy(src, 'test5.Rmd', overwrite = TRUE)
      
      library(rmarkdown)
      out <- a()
      file.rename(out, file)
    }
  )
  
  

}

shinyApp(ui = ui, server = server)
解决思路

问题根源

当切换到Global类型时,param控件被移除,Shiny不会主动清除input$param的缓存值,导致切回Por instituciones时,input$param仍保留之前的旧值,而非新选择的内容。

修复方案

方案一:强制初始化动态生成的param控件

修改renderUI中的selectInput,每次生成控件时指定默认选中项,确保重新渲染时重置值:

output$ui <-  renderUI({
  if (input$input_type == "Por instituciones") {
    selectInput("param", "Seleccione la institución:", 
                choices = c("BDE", "DIGERCIC"),
                selected = "BDE") # 指定第一个选项为默认值
  } 
})

方案二:用reactiveVal存储param的有效值

在server中创建reactiveVal跟踪param的当前有效值,避免依赖被移除的控件:

server <- function(input, output) {
  current_param <- reactiveVal(NULL)
  
  # 实时更新param的有效值
  observe({
    if (input$input_type == "Por instituciones") {
      current_param(input$param)
    } else {
      current_param(NULL)
    }
  })

  output$ui <-  renderUI({
    if (input$input_type == "Por instituciones") {
      selectInput("param", "Seleccione la institución:", 
                  choices = c("BDE", "DIGERCIC"))
    } 
  })

  a <-  eventReactive(input$generate, {
    if(input$input_type == "Por instituciones")  {
      print(current_param()) # 使用存储的有效值
      rmarkdown::render("C:/Users/santy/Documents/test5.Rmd",
                        params = list(institucion = current_param(),
                                      fecha = input$date))
      includeHTML("C:/Users/santy/Documents/test5.html")
    } else {
      rmarkdown::render("C:/Users/santy/Documents/Reporte_seguimiento110523.Rmd",
                        params = list(fecha = input$date))
      includeHTML("C:/Users/santy/Documents/Reporte_seguimiento110523.html")
    }
  })

  # 其余代码保持不变...
}

方案三:用conditionalPanel替代renderUI

将动态显示的param用conditionalPanel实现,控件始终存在于DOM中(仅隐藏),Shiny会持续跟踪其值:

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      titlePanel("Repotería seguimiento PEIPRDCI"),
      selectInput("input_type", "Tipo reporte",
                  c("Global", "Por instituciones")), 
      # 替换uiOutput为conditionalPanel
      conditionalPanel(
        condition = "input.input_type == 'Por instituciones'",
        selectInput("param", "Seleccione la institución:", 
                    choices = c("BDE", "DIGERCIC"))
      ),
      selectInput("date", "Seleccione la fecha:", 
                  choices = c("2023-01-01", "2023-02-01")), 
      actionButton("generate", "Generar reporte"), 
      downloadButton('downloadReport', "Descargar")
    ),
    mainPanel(
      htmlOutput("report")
    )
  )
)

内容的提问来源于stack exchange,提问作者Santiago Valdivieso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 07:00:19