【问题标题】:R Shiny, how to update variable within observeEvent callR Shiny,如何在observeEvent调用中更新变量
【发布时间】:2017-08-03 06:19:13
【问题描述】:

我无法在 observeEvent 调用中更新列表。

该列表称为Participants,是一个列表列表 - 即每个用户的配置文件。 Participants 应该由任何用户在某个 observeEvent 调用中更新。

我尝试让变量反应和非反应,但它不起作用。

下面是一个最小的工作示例

ui.R

用户代码

library(shiny)

shinyUI( fluidPage(
    sidebarLayout(
        #---------------------------------------------------
        # accept user transid
        sidebarPanel(
            numericInput("transid", "Transid", 0), 
            actionButton("accept", "Accept" )
        ),
        #---------------------------------------------------
        # Return user spreadsheet
        mainPanel( verbatimTextOutput("userSpreadSheet"))
))
)

服务器.R

服务器代码 #------------------------------------------------ -- ################## # 定义 图书馆(闪亮)

## Create Participant List
ParticipantsDF <- data.frame(
    Name=stringi::stri_rand_strings(n=20, length=8, pattern="[a-z]"),
    ID=paste0("JA",1:20) ) 
spreadsheet  <- list(data.frame(foo=1:10, bar=runif(10), transid=NA) )
Participants <- apply( ParticipantsDF, 1, function(e){
     c( as.list(e), spreadsheet=spreadsheet ) })
ParticipantIDs <- ParticipantsDF$ID
ParticipantNames <- ParticipantsDF$Name

## Update Participants by changing a person
## based on user input of transid value
    ## change persons sublist named ``transid''
update_person <- function(transid, pid, participants){
    ## Which User
    userProfile_u <- participants[[pid]]
    ## Update User next transid to TRUE
    rows_vacant <- is.na(userProfile_u$spreadsheet$transid)
    row_update <- head( which(rows_vacant),1)
    userProfile_u$spreadsheet[row_update, "transid"] <- TRUE 
    ## Update Participants
    participants[[pid]] <- userProfile_u
    Participants <<- participants
}

#----------------------------------------------------------------------
##################
# Server 
server <- function( input, output, session){

    #---------------------------------------------------
    # Get authorized user: requires shiny-server-pro
    user <- session$user

    #---------------------------------------------------
    # Return user profile
    userPID <- which(ParticipantIDs == session$user )
    userProfile <- Participants[[userPID]]
    #---------------------------------------------------
    # When user clicks ``accept'', update Participants
    observeEvent(input$accept, {
        update_person(
            input$transid,
            userPID,
            Participants
        )
    })
    #---------------------------------------------------
    # Display spreadsheet to user
    ## Does Not Update!
    output$userSpreadSheet <- renderPrint({
        Participants[[userPID]][["spreadsheet"]] })
    ## Updates (Based on Accepted Answer)
    #ReactiveParticipants <- reactiveValues(Participants=Participants)
    #output$userSpreadSheet <- renderPrint({
    #    ReactiveParticipants$Participants[[userPID]][["spreadsheet"]]
    #})
    #observe({  invalidateLater(100)
    #    ReactiveParticipants$Participants <<- Participants
    #})
}
shinyServer(server)

如果我编辑上面的代码不使用 renderPrint reactiveValues,那么它仍然不起作用。

【问题讨论】:

    标签: r shiny reactive-programming


    【解决方案1】:

    看起来反应性可能存在一些问题。据我所知,session$user 在应用程序运行时(对于该用户)不会更改,因此响应式语句及其依赖项可能根本不会执行第二次(这就是最后一块不更新的原因)。

    第二部分我不确定isolate 如何在Participants 上工作,因为这是全局环境中的静态变量,而不是反应对象。您能否提供一段完全可重现的代码?


    编辑: 您的示例实际上非常接近,主要问题是您试图在观察者(renderPrint)中读取静态全局变量。由于您的函数update_person 在将参与者保存到全局环境时也会返回参与者,因此您可以直接将其用作 reactiveValue 然后调用它:

    server <- function(input, output, session){
      #---------------------------------------------------
      # Get authorized user: requires shiny-server-pro
      user <- session$user
    
      #---------------------------------------------------
      # Return user profile
      userPID <- which(ParticipantIDs == user )
      userProfile <- Participants[[userPID]]
    
      rv <- reactiveValues(Participants = Participants)
    
      observeEvent(input$accept, {
         rv$Participants <- update_person(
           input$transid,
           userPID,
           Participants
         )
      })
    
      output$userSpreadSheet <- renderPrint({
        rv$Participants[[userPID]][["spreadsheet"]]
      })
    }
    

    希望对你有帮助。

    【讨论】:

    • 我也认为它与反应性有关。我做了一个完全可重现的例子。
    猜你喜欢
    • 1970-01-01
    • 2021-02-13
    • 2021-12-26
    • 2021-12-21
    • 2017-11-06
    • 2022-01-19
    • 2017-02-23
    • 1970-01-01
    • 2018-12-05
    相关资源
    最近更新 更多