2016-09-25 52 views
1

我有一个复杂的Shiny应用程序。我有一个selectize输出对象,selectTest,它的值由反应对象isTestReady读取。 isTestReady评估某些条件是否满足selectTestisTestReady然后用于各种块作为门。我已将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()之前运行。

+0

相关,但不是一个解决方案 - http://stackoverflow.com/questions/30378310/shiny-renderui-selectinput-returned-null?rq=1 – TheComeOnMan

+1

可以绑定'eventReactives'也与其他反应。像这样:'eventReactives {temp(),{}}'。 –

+0

@PorkChop,我正在基于'temp()创建新的输出对象,所以'eventReactive'不是一个选项。除非我做杂乱的“本地”等业务。 – TheComeOnMan

回答

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) 
+0

谢谢。这个建议与我在评论中提到的链接类似。 – TheComeOnMan

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()) 
    '-' 
    }) 

} 
+0

谢谢。这看起来有希望。我会在我的应用程序中检查一次(这可能需要我一两天)。我会检查标记答案,如果它的工作。 – TheComeOnMan

+0

我有一种感觉,这基本上阻止了其他观察块的执行,因为temp的NULL值,并且实际上并没有强制执行temp的评估。 – TheComeOnMan