强制评估反应块

时间:2016-09-25 13:52:04

标签: r shiny

我有一个复杂的Shiny应用程序。我有一个selectize输出对象selectTest,其值由被动对象isTestReady读取。 isTestReady评估selectTest是否满足某些条件。然后将isTestReady用作各种块作为门。我已将selectTest设置为outputOptions(suspendWhenHidden = F, priority 999),以确保它立即启动并运行。

在运行时,我注意到selectTest的块首先被执行。在此之后运行isTestReady时,它仍会将selectTest的值读取为NULL,而不是在第一个块中分配给selectTest的任何值。在返回重新评估isTestReady之前,Shiny会经历许多其他模块。在重新评估之后,再次调用其他块,现在它们运行良好。

这是预期的行为吗?如果是这样,关于如何使我的场景按照我描述的方式发挥的任何想法?

示例 -

library(shiny)
library(shinydashboard)


# Setup Shiny app UI components -------------------------------------------

ui <- dashboardPage(

   dashboardHeader(),
   ## Sidebar content
   dashboardSidebar(
      sidebarMenu(
         uiOutput('someelement'),
         textOutput('temp2')
      )
   ),
   dashboardBody(  )

)


# Setup Shiny app back-end components -------------------------------------

server <- function(input, output) {

   output[['someelement']] = renderUI({
      selectizeInput(
         inputId = 'someelement',
         choices = letters,
         selected = letters[1],
         label = 'Custom Functions',
         multiple = F
      )
   })

   outputOptions(
      output,
      'someelement',
      suspendWhenHidden = F
   )

   temp = reactive({
      print('?')
      input[['someelement']]
   })

   observe({
      print('!')
      print(temp())
   })

   output[['temp2']] = renderText({
      print('!!')
      print(temp())
      '-'
   })

}

# Render Shiny app --------------------------------------------------------

shinyApp(ui, server)

输出到上述应用程序的控制台的日志如下所示 -

[1] "!"
[1] "?"
NULL
[1] "!!"
NULL
[1] "!"
[1] "?"
[1] "a"
[1] "!!"
[1] "a"

有什么办法可以避免那个NULL?在我的应用中,有很多块寻找temp(),所有这些块都在temp()之前运行。

2 个答案:

答案 0 :(得分:0)

尝试使用observe()和reactiveValues(),查看this question的已接受答案。 reactive()是懒惰的。

我编辑了您的问题,因此文字中的变量名称与您的代码相匹配。但我可能会想念你。像这样的东西?

library(shiny)
library(shinydashboard)


# Setup Shiny app UI components -------------------------------------------

ui <- dashboardPage(

  dashboardHeader(),
  ## Sidebar content
  dashboardSidebar(
    sidebarMenu(
      uiOutput('ui_selectTest') 
    )
  ),
  dashboardBody(  )

)


# Setup Shiny app back-end components -------------------------------------

server <- function(input, output) { 

  rv<- reactiveValues()

  output$ui_selectTest = renderUI({
    selectizeInput(
      inputId = 'selectTest',
      choices = letters,
      selected = letters[1],
      label = 'Custom Functions',
      multiple = F
    )
  })

  observe(
    if(!is.null(input$selectTest)) { 
      #check select test
      rv$testReady <- input$selectTest
    }
  )

  observeEvent(rv$testReady,{
    print(  rv$testReady  )
  })
} 

shinyApp(ui, server)

答案 1 :(得分:0)

只需在每个反应块中使用validate即可检查所有需要的输入和条件。您的服务器功能将看起来像这样

server <- function(input, output) {

  output[['someelement']] = renderUI({
    selectizeInput(
      inputId = 'someelement',
      choices = letters,
      selected = letters[1],
      label = 'Custom Functions',
      multiple = F
    )
  })

  outputOptions(
    output,
    'someelement',
    suspendWhenHidden = F
  )

  temp = reactive({
    #check if someelement is a valid input
    validate(need(input[['someelement']] %in% letters, "need input")) 
    print('?')
    input[['someelement']]
  })

  observe({
    #check if tmp() has already been evaluated
    validate(need(temp(), "need tmp"))  
    print('!')
    print(temp())
  })

  output[['temp2']] = renderText({
    validate(need(temp(), "need tmp"))
    print('!!')
    print(temp())
    '-'
  })

}