2017-06-20 6 views
0

Shinyは最初の読み込み時に他のタブで使用される関数を実行しています。最小限の例として、wch hereから採用されている次のアプリを見てください。このアプリには2つのメニュー項目があります。サイドバーメニュー項目Aをクリックすると、output$A_panelからメニュー項目を生成するrenderUI関数が実行されます。このアプリは完全にそれを行います。しかし、Rコンソールを見ると、Inside A PanelInside B Panelの両方が表示されます。これは、ユーザーがメニュー項目Bをクリックしない限り、アプリケーションが最初に読み込まれ、光っているだけで、両方の関数が実行されたことを意味します。shiny - 最初の読み込み時に異なるタブの機能が実行される

私は同様の手法を使用するアプリを持っていますが、私は最初の負荷でやりたくないものです。それは私のアプリを非常に遅くする。この自動実行が起こらないようにする方法はありますか?

library(shiny) 
library(shinydashboard) 

ui <- dashboardPage(
     dashboardHeader(), 
     dashboardSidebar(
sidebarMenu(id = "sidebarmenu", 
      menuItem("A", tabName = "a", icon = icon("group", lib="font-awesome")), 
      menuItem("B", tabName = "b", icon = icon("check-circle", lib = "font-awesome")), 
      conditionalPanel("input.sidebarmenu === 'a'", 
          uiOutput('A_panel') 
          ), 
      conditionalPanel("input.sidebarmenu === 'b'", 
          uiOutput('B_panel') 
          ) 
), 
sliderInput("x", "Outside of menu", 1, 100, 50) 
), 
dashboardBody() 
) 

server <- function(input, output) { 

output$A_panel <- renderUI({ 
     cat('Inside A Panel \n') 
     sliderInput("b", "Under A", 1, 100, 50) 
}) 
output$B_panel <- renderUI({ 
     cat('Inside B Panel \n') 
     sliderInput("b", "Under B", 1, 100, 50) 
     }) 

} 
shinyApp(ui, server) 

答えて

1

ConditionalPanelは、実行ではなくUIの表示を制御します。 この場合の迅速な修正は、以下のようにsidebarmenuの値に基づいて関数から抜け出すことです。
"b"出力のrenderUIは、メニューが "b"のときにのみ実行されます。 sidebarmenuの変化がrenderUIをトリガーするため、

library(shiny) 
library(shinydashboard) 

ui <- dashboardPage(
    dashboardHeader(), 
    dashboardSidebar(
    sidebarMenu(id = "sidebarmenu", 
       menuItem("A", tabName = "a", icon = icon("group", lib="font-awesome")), 
       menuItem("B", tabName = "b", icon = icon("check-circle", lib = "font-awesome")), 
       conditionalPanel("input.sidebarmenu == 'a'", 
           uiOutput('A_panel') 
       ), 
       conditionalPanel("input.sidebarmenu == 'b'", 
           uiOutput('B_panel') 
       ) 
    ), 
    sliderInput("x", "Outside of menu", 1, 100, 50) 
), 
    dashboardBody() 
) 

server <- function(input, output) { 

    output$A_panel <- renderUI({ 
    if(input$sidebarmenu != "a") return() 
    cat('Inside A Panel \n') 
    sliderInput("b", "Under A", 1, 100, 50) 
    }) 
    output$B_panel <- renderUI({ 
    if(input$sidebarmenu != "b") return() 
    cat('Inside B Panel \n') 
    sliderInput("b", "Under B", 1, 100, 50) 
    }) 

} 
shinyApp(ui, server) 

しかし、この実装では計算は、メニューを切り替えるたびに行われています。 これは、メニュー "b"をロードするときに必要な計算に関心があるため、正確には望み通りではないかもしれません。 "b"メニューが選択された後にのみ計算が行われることがありますが、再度は実行しないことをお勧めします。

このようにするには、outputBがレンダリングされたかどうかを覚えておいてreactiveValuesを使用してください。既にレンダリングされている場合はrenderUIを終了してください。 以下の実装では、メッセージは1回だけ表示されます。

library(shiny) 
library(shinydashboard) 

ui <- dashboardPage(
    dashboardHeader(), 
    dashboardSidebar(
    sidebarMenu(id = "sidebarmenu", 
       menuItem("A", tabName = "a", icon = icon("group", lib="font-awesome")), 
       menuItem("B", tabName = "b", icon = icon("check-circle", lib = "font-awesome")), 
       conditionalPanel("input.sidebarmenu == 'a'", 
           uiOutput('A_panel') 
       ), 
       conditionalPanel("input.sidebarmenu == 'b'", 
           uiOutput('B_panel') 
       ) 
    ), 
    sliderInput("x", "Outside of menu", 1, 100, 50) 
), 
    dashboardBody() 
) 

server <- function(input, output) { 

    RV <- reactiveValues(b_ui_flg=FALSE) 

    output$A_panel <- renderUI({ 
    if(input$sidebarmenu != "a") return() 
    cat('Inside A Panel \n') 
    sliderInput("b", "Under A", 1, 100, 50) 
    }) 

    observeEvent(input$sidebarmenu, { 
    if(input$sidebarmenu != "b") return() 
    if (RV$b_ui_flg) return() 
    RV$b_ui_flg <- TRUE 
    cat('Inside B Panel \n') 
    output$B_panel <- renderUI({ 
     sliderInput("b", "Under B", 1, 100, 50) 
    }) 
    }) 

} 
shinyApp(ui, server) 
+0

優れた答えです。私は 'if(input $ sidebarmenu!=" a ")return()'の変形を試みました。それは私にとってはうまくいかなかった。しかし、私は非常に古いバージョンの光沢がありました。今私はそれを責めるだろう。 +1の2番目のアプローチです。 – Sal

関連する問題