How to combine loops and reactive expressions


I am working on "for loops" in RShiny, I want to plot its result according to selected date. However, I have difficulty in determining reactive contents in server. It didn't worked. Here is my related code in server:

server <- function(input, output){
  training=reactive({dat%>% filter(as.Date(dat$Date)>=as.Date(input$daterange[1]) & as.Date(dat$Date)<=as.Date(input$daterange[2])  )}) 
  for (i in seq(reactive(nrow(training())))){
    limit2=reactive(training()$EventTime[i]+ minutes(10))
    flood_test=reactive(training()%>% filter(training()$EventTime[i] <= training()$EventTime & training()$EventTime <= limit2()))

The errors I encountered are

Error in .getReactiveEnvironment()$currentContext() : 
  Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

Error in result()[t, 1] = i : invalid (NULL) left side of assignment

I did many trials but I could not make it work. Could you please help me?

Thank you

It seems like you're thinking of reactive() as a creating typical R variable, but it isn't. A reactive expression gives a recipe for how to compute a value, and Shiny determines when that value needs to updated (based on what other reactive values it depends on). For one, this implies that reading a reactive value outside of a reactive context (e.g., training()$EventTime[i]) is not allowed, and setting the value of a reactive expression (e.g., result()[t,2]=training()$EventTime[i]) is not allowed. I highly recommend reading the chapter on Basic Reactivity from the new (in progress) Mastering Shiny book

Anyway, you should be providing the instructions for computing result in a reactive expression, rather than writing a normal R expression that tries to read/set reactives

result <- reactive({
  rows <- lapply(seq(nrow(training())), function(i) {
    limit2 <- training()$EventTime[i]+ minutes(10)
    flood_test <- training()%>% filter(training()$EventTime[i] <= training()$EventTime & 
    training()$EventTime <= limit2)
    alarm_number <- nrow(flood_test)
    data.frame(et = training()$EventTime[i], num = alarm_number())
  dat <- dplyr::bind_rows(rows)
  dat[!duplicated(dat$et), ]
1 Like