2016-09-11 35 views
21

यह प्रश्न this one से संबंधित है। दोनों एक ही कार्यक्षमता उत्पन्न कर सकते हैं, लेकिन कार्यान्वयन थोड़ा अलग है। एक महत्वपूर्ण अंतर यह है कि reactiveValue एक कंटेनर है जिसमें कई मान हो सकते हैं, जैसे input$shiny documentation कार्यक्षमता को आमतौर पर reactive() का उपयोग करके कार्यान्वित किया जाता है, लेकिन ज्यादातर मामलों में मुझे reactiveValues() अधिक सुविधाजनक लगता है। क्या यहां कोई पकड़ है? क्या उन दोनों के बीच कोई अन्य बड़ा अंतर है जो मुझे पता नहीं हो सकता है? क्या ये दो कोड स्निपेट बराबर हैं?आर चमकदार: प्रतिक्रियाशील वैल्यू बनाम प्रतिक्रियाशील

देखें एक ही example code का उपयोग कर कार्यान्वित:

  1. एक प्रतिक्रियाशील अभिव्यक्ति:

    library(shiny) 
    
    ui <- fluidPage( 
        shiny::numericInput(inputId = 'n',label = 'n',value = 2), 
        shiny::textOutput('nthValue'), 
        shiny::textOutput('nthValueInv') 
    ) 
    
    fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2)) 
    
    server<-shinyServer(function(input, output, session) { 
        currentFib   <- reactive({ fib(as.numeric(input$n)) }) 
        output$nthValue <- renderText({ currentFib() }) 
        output$nthValueInv <- renderText({ 1/currentFib() }) 
    }) 
    
    shinyApp(ui = ui, server = server) 
    
  2. एक प्रतिक्रियाशील मूल्य:

    library(shiny) 
    
    ui <- fluidPage( 
        shiny::numericInput(inputId = 'n',label = 'n',value = 2), 
        shiny::textOutput('nthValue'), 
        shiny::textOutput('nthValueInv') 
    ) 
    
    fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2)) 
    
    server<-shinyServer(function(input, output, session) { 
        myReactives <- reactiveValues() 
        observe( myReactives$currentFib <- fib(as.numeric(input$n)) ) 
        output$nthValue <- renderText({ myReactives$currentFib }) 
        output$nthValueInv <- renderText({ 1/myReactives$currentFib }) 
    }) 
    
    shinyApp(ui = ui, server = server) 
    
+2

जब आप पूरा कर लें तो कृपया इस विषय को संदर्भ http://stackoverflow.com/documentation/shiny/topics –

उत्तर

34

एक पकड़ है, हालांकि यह आपके उदाहरण में नहीं आएगा।

चमकदार डेवलपर्स reactive() तैयार किया गया आलसी हो सकता है, जिसका अर्थ है कि उसमें शामिल अभिव्यक्ति केवल जब वह अपने आश्रितों में से एक ने कहा जाता है निष्पादित किया जाएगा। जब इसकी प्रतिक्रियाशील निर्भरताओं में से एक बदल जाती है, तो यह अपने कैश को साफ़ करती है और अपने आश्रितों को सूचित करती है, लेकिन उन आश्रितों में से किसी एक से पूछे जाने तक इसे निष्पादित नहीं किया जाता है। , (तो अगर कहते हैं, अपने एकल निर्भर एक छिपे हुए टैब पर एक textOutput() तत्व है, यह वास्तव में जब तक कि टैब खोला जाए निष्पादित नहीं किया जाएगा।)

observe(), दूसरे हाथ पर उत्सुक है; जिस अभिव्यक्ति में यह शामिल है, उसे तब भी निष्पादित किया जाएगा जब इसकी प्रतिक्रियाशील निर्भरताओं में से कोई भी बदला जाता है - भले ही उसके किसी भी आश्रित द्वारा इसकी कीमत की आवश्यकता न हो (और वास्तव में में कोई आश्रित नहीं है)। इस उत्सुकता वांछनीय है जब आप observe() को इसके दुष्प्रभावों के लिए बुला रहे हैं, लेकिन यह कचरा हो सकता है जब आप इसका उपयोग केवल अन्य प्रतिक्रियाशील अभिव्यक्तियों या रेखा के अंतराल पर अपनी सामग्री के वापसी मूल्य को पारित करने के लिए कर रहे हैं ।

जो चेंग ने "प्रभावी प्रतिक्रियाशील प्रोग्रामिंग", available here पर अपने 2016 चमकदार डेवलपर सम्मेलन प्रस्तुति में इस भेद को काफी अच्छी तरह से समझाया। प्रस्तुति के दूसरे घंटे में विशेष रूप से 30:20 के आसपास शुरू होने वाला थोड़ा सा देखें। यदि आप 40:42 तक देखते हैं (झपकी दें और आप इसे याद करेंगे!) वह संक्षेप में observe()/reactiveValue() संयोजन के व्यवहार को संक्षेप में दर्शाता है।

+0

अंतर्दृष्टि के लिए धन्यवाद। मुझे लगता है कि घर लेना संदेश यह है कि निरीक्षण/प्रतिक्रियाशील उपयोग का उपयोग कम कुशल हो सकता है। लेकिन .. जैसा कि दत्ताली द्वारा इंगित किया गया है, वहां मामले प्रतिक्रियाशील थे वैलेंस को संकल्पना/कार्यान्वित करना आसान है। चमकदार दस्तावेजों में इसे बेहतर समझाया जाना चाहिए। –

19

यह सच है कि दो निर्माणोंसमान हैं, और कई बार आप अपनी समस्या का समाधान करने के लिए किसी एक का उपयोग कर सकते हैं। लेकिन यह आमतौर पर एक या दूसरे का उपयोग करने के लिए अधिक समझ में आता है।

फिबोनैकी मामले में, मुझे लगता है कि का उपयोग कर एक reactive() अभिव्यक्ति अधिक समझ में आता है, क्योंकि currentFib एक मूल्य है कि अर्थात्। जब input$n परिवर्तन, प्रतिक्रियाशील मूल्य के हिसाब से अद्यतन किया जाना चाहिए, या बहुत विशिष्ट उम्मीद के मुताबिक समय में संशोधित किया जाना चाहिए (है उस परिवर्तन के लिए पर प्रतिक्रिया दें)।

लेकिन कुछ अन्य मामलों में यह reactiveValues का उपयोग करने के लिए आसान और बेहतर हो सकता है। मैं दो उदाहरण दिखाऊंगा।

पहले, जब भी आप एक चर है कि आप राज्य में किसी प्रकार का होने (बल्कि सिर्फ एक अलग मूल्य पर प्रतिक्रिया से अपडेट किया जा रहा) के रूप में के बारे में सोच है, मैं reactiveValues का उपयोग कर लगता है कि बेहतर है।

उदाहरण:

library(shiny) 

ui <- fluidPage(
    "Total:", 
    textOutput("total", inline = TRUE), 
    actionButton("add1", "Add 1"), 
    actionButton("add5", "Add 5") 
) 

server <- function(input, output, session) { 
    values <- reactiveValues(total = 0) 

    observeEvent(input$add1, { 
    values$total <- values$total + 1 
    }) 
    observeEvent(input$add5, { 
    values$total <- values$total + 5 
    }) 
    output$total <- renderText({ 
    values$total 
    }) 
} 

shinyApp(ui = ui, server = server) 

उपरोक्त कोड में, हम एक total चर कि परिवर्तनशील राज्य है, और यह एक विशिष्ट चर के रूप में यह के बारे में सोच और इस तरह के रूप में उपयोग करने और अधिक सहज है। जब मैं reactiveValues का उपयोग करता हूं तो यह सबसे आम मामला है।

मैं भी reactiveValues का उपयोग करता हूं जब एक चर कई स्थानों में अपडेट किया जा सकता है।

library(shiny) 

fib <- function(n) ifelse(n < 3, 1, fib(n - 1) + fib(n - 2)) 

ui <- fluidPage(
    selectInput("nselect", "Choose a pre-defined number", 1:10), 
    numericInput("nfree", "Or type any number", 1), 
    "Fib number:", 
    textOutput("nthval", inline = TRUE) 
) 

server <- function(input, output, session) { 
    values <- reactiveValues(n = 1) 

    observeEvent(input$nselect, { 
    values$n <- input$nselect 
    }) 
    observeEvent(input$nfree, { 
    values$n <- input$nfree 
    }) 
    output$nthval <- renderText({ 
    fib(as.integer(values$n)) 
    }) 
} 

shinyApp(ui = ui, server = server) 

यह उदाहरण फिबोनैकी के संदर्भ में थोड़ा अजीब लग सकता है लेकिन उम्मीद है कि: फिबोनैकी उदाहरण से उधार के लिए, निम्न चमकदार अनुप्रयोग, जहां n संख्या या तो दो में से एक आदानों द्वारा निर्धारित किया जा सकता है पर विचार आप देख सकते हैं कि कुछ अन्य जटिल ऐप्स में, कभी-कभी आप अलग-अलग स्थानों में एक चर के मान को सेट करना चाहते हैं और यह एक प्रतिक्रियाशील अभिव्यक्ति के बजाय एक प्रतिक्रियाशील वैल्यू का उपयोग करके इसे करने के लिए अधिक सहज हो सकता है जिसे एक ब्लॉक में लागू किया जाना चाहिए।

उम्मीद है कि यह सहायक था और समझ में आता है। बेशक यह केवल इस विषय पर मेरा निजी लेना है, यह आवश्यक नहीं है कि चमकदार डेवलपर्स का इरादा क्या है, लेकिन इस तरह मैंने दो तरीकों का उपयोग करना सीखा है।

संबंधित मुद्दे