increment reactivevalue inside invalidatelater observer

戏子无情 提交于 2019-12-11 06:07:01

问题


I'm trying to build shinyapp to make a very simple quizz. I have a data.frame with 10 questions, and the user clicks to answer either 0 or 1. It worked until I tried to implement a timer / countdown so that the next question appears automatically after 5 seconds, using an invalidateLater() call.

The current question number is stored in a reactiveValues() object, variable i

When I add my observe function, the app stopped working and did not display the question. My code is here:

init = data.frame(question=paste("question", 1:10), correct=c(1,1,1,1,1,0,0,0,0,0), answer=NA, stringsAsFactors = FALSE)
library(shiny); library(shinydashboard)
ui=dashboardPage(dashboardHeader(title = "questionnaire"),dashboardSidebar(),dashboardBody(
        fluidRow(box(width = 6, title="how it works..", p("balblabla"))),
        fluidRow(
            box(width = 12, background = "orange",
          fluidRow(
            box(width = 12, 
                verbatimTextOutput("question"),
                tags$head(tags$style("#question{font-size: 20px; text-align: left; font-weight: bold;}"))
            ),
            box(width = 12,
                actionButton("negative", "answer 0", width = '30%'),
                actionButton("positive", "answer 1", width = '30%')
            ))))))
server <- function(input, output, session) {
  vals = reactiveValues(df = init, i=1)
  output$question <- renderText({vals$df[vals$i, "question"]})
  observe({
    invalidateLater(5000)
    vals$i <- vals$i + 1
  })
  observeEvent(input$negative, ignoreInit=TRUE, {
    vals$df[vals$i, "answer"] = 1
    if (vals$df[vals$i, "correct"]==1){
      showNotification("WRONG!", type="error", duration=1, closeButton = FALSE)
    } else {
      showNotification("CORRECT!", type="message", duration=1, closeButton = FALSE)
    }})
  observeEvent(input$positive, ignoreInit=TRUE, {
    vals$df[vals$i, "answer"] = 1
    if (vals$df[vals$i, "correct"]==0){
      showNotification("WRONG!", type="error", duration=1, closeButton = FALSE)
    } else {
      showNotification("CORRECT!", type="message", duration=1, closeButton = FALSE)
    }})
}
shinyApp(ui, server)

Can you help me fix this observe statement, i Don't know what's going wrong here.


回答1:


You need to isolate the increment of the index within this observer:

  observe({
    invalidateLater(5000)
    vals$i <- vals$i + 1
  })

, otherwise you'll send it in an infinite loop because a value that it "observes" is changed within the observer itself, constantly triggering re-evaluation irrespective from elapsed time (you can verify this by adding a print(vals$i) instruction in your current code, at the end of the observer.

So, something like this seems to work:

  vals = reactiveValues(df = init, i=0)
  output$question <- renderText({vals$df[vals$i, "question"]})
  observe({
    invalidateLater(5000)
    isolate(vals$i <- vals$i + 1)
  })

Note that I changed the initialization of i to zero to avoid skipping a question in initialization.

HTH.



来源:https://stackoverflow.com/questions/54364680/increment-reactivevalue-inside-invalidatelater-observer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!