R Shiny - Понимание разницы между наблюдением и наблюдением события при обновлении взаимозависимых входных данных - PullRequest
1 голос
/ 26 февраля 2020

Приложение ниже имеет два взаимозависимых числовых входа, a и b. Значение input$a равно 1-input$b, а значение input$b равно 1-input$a. Всякий раз, когда пользователь изменяет значение ввода, я хотел бы обновить значение другого соответственно. Код ниже содержит два подхода:

  1. Один наблюдатель
  2. Два отдельных наблюдателя - один слушает изменения a и обновляет b, а другой слушает b и обновления a.

Когда я пытаюсь 1), входы застревают в бесконечном l oop, но я не уверен, что понимаю почему. Если пользователь изменяет b, тогда запускается наблюдатель, и значение a обновляется до 1-b. Поскольку значения обоих входов теперь актуальны, больше нет изменений на input$a или input$b, и наблюдатель не должен запускаться снова, пока пользователь не внесет другое изменение. Но это не так.

Чем именно подход 1) отличается от подхода 2)? Почему 1) застревает в oop, а 2) нет?

library(shiny)

shinyApp(
  ui = fluidPage(
    numericInput('a','a', value = 0.5, max = 1, min = 0),
    numericInput('b','b', value = 0.5, max = 1, min = 0)
  ),
  server = function(input, output, session) {

    # Using a single observer ----
    observe({

      updateNumericInput(session, 'a', value = 1-req(input$b))

      updateNumericInput(session, 'b', value = 1-req(input$a))

      print(input$a)

    })

    # Using separate observers ----
    # observeEvent(input$b, {
    #   updateNumericInput(session, 'a', value = 1-input$b)
    # })
    # 
    # observeEvent(input$a, {
    #   updateNumericInput(session, 'b', value = 1-input$a)
    # })

  }
)

1 Ответ

1 голос
/ 26 февраля 2020

В документации observe и observeEvent написано:

  • observe

Наблюдатель похож на реактивное выражение в том смысле, что он может читать реактивные значения и вызывать реактивные выражения, и будет автоматически выполняться при изменении этих зависимостей. [...] [O] bservers используют нетерпеливую оценку; как только их зависимости меняются, они планируют повторное выполнение.

В вашем примере observe никогда не прекращает "наблюдение" и обновляет ввод, как только другие изменения, даже если пользователь ничего не делает Следовательно, вы находитесь в бесконечном l oop, поскольку каждый из двух входов зависит от другого.

  • observeEvent

[S] ometimes Вы хотите подождать, пока пользователь не предпримет конкретное действие c, например щелчок по actionButton (), перед вычислением выражения или выполнением действия. [...] Используйте Наблюдение за событием всякий раз, когда вы хотите выполнить действие в ответ на событие.

Следовательно, observeEvent необходимо, чтобы пользователь выполнил действие для запуска функции внутри. В вашем примере ввод «а» будет обновлен только в том случае, если пользователь вручную изменит ввод «b» и наоборот. Вот почему observeEvent работает в этом сценарии, а observe - нет.

Edit: , чтобы получить более четкие результаты для l oop, созданного при использовании observe, вот немного модифицированная версия примера в OP:

library(shiny)

shinyApp(
  ui = fluidPage(
    numericInput('a','a', value = NULL, max = 1, min = 0),
    numericInput('b','b', value = NULL, max = 1, min = 0)
  ),
  server = function(input, output, session) {

    # Using a single observer ----
    observe({

      updateNumericInput(session, 'a', value = 1-req(input$b))

      updateNumericInput(session, 'b', value = 1-req(input$a))

      print(paste0("a = ", input$a))
      print(paste0("b = ", input$b))

    })


    # Using separate observers ----
    # observeEvent(input$b, {
    #   updateNumericInput(session, 'a', value = 1-input$b)
    # })
    # 
    # observeEvent(input$a, {
    #   updateNumericInput(session, 'b', value = 1-input$a)
    # })

  }
)

Осторожно с интерпретацией: печатаются начальные значения a и b. Затем создаются новые значения a и b, но новое значение b зависит от первого значения a (не от второго значения a). Третьи значения a и b будут зависеть от вторых значений a и b, et c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...