I have a shiny app which would like to use reactiveFileReader to dynamically update a data store. Ideally, the new data would be appended to old data, but when I make the assignment within the app, I get the following error:
Error: C stack usage 7970144 is too close to the limit
Here's a (failing) reprex; note that the reactive the_time() is getting invalidated in order to simulate some new incoming data in lieu of reactiveFileReader. A functioning app would append times to an ever growing table every second.
library(shiny)
# DOESN"T WORK
# The UI
ui <- fluidPage( tableOutput("timeTable") )
server <- function(input, output, session) {
time_accum <- reactive( data.frame(time = NULL) )
## the_time is a drop in replacement for reactiveFileReeader for this reprex
the_time <- reactive({
invalidateLater(1000, session)
data.frame(time = as.character(Sys.time()))
})
## the key step, which seems to be the fail point
time_accum <- reactive( bind_rows(time_accum(), the_time()) )
output$timeTable <- renderTable( time_accum() )
}
# Run the app
shinyApp(ui = ui, server = server)
Incidentally, below is a version that updates the time, but doesn't accumulate the old values, in case this version is somehow helpful. thanks in advance for any help
library(shiny)
ui <- fluidPage( tableOutput("timeTable") )
server <- function(input, output, session) {
time_accum <- reactive( data.frame(time = NULL) )
## the_time is a drop in replacement for reactiveFileReeader for this reprex
the_time <- reactive({
invalidateLater(1000, session)
data.frame(time = as.character(Sys.time()))
})
## the key step, which seems to be the fail point
#time_accum <- reactive( bind_rows(time_accum(), the_time()) )
output$timeTable <- renderTable( the_time() )
}
shinyApp(ui = ui, server = server)
Hi @cawthm. The script loop so deep and complicate. I clean up some and see if the script is what you wanted.
library(shiny)
library(tidyverse)
# DOESN"T WORK
# The UI
ui <- fluidPage( tableOutput("timeTable") )
server <- function(input, output, session) {
vals <- reactiveValues( time_accum = data.frame(time = NULL) )
## the_time is a drop in replacement for reactiveFileReeader for this reprex
the_time <- reactive({
invalidateLater(1000, session)
data.frame(time = as.character(Sys.time()))
})
## the key step, which seems to be the fail point
observe(
{
time <- the_time()
isolate(vals$time_accum <- bind_rows(vals$time_accum, time))
}
)
# vals$time_accum <- reactive( bind_rows(vals$time_accum, the_time()) )
output$timeTable <- renderTable( vals$time_accum )
}
# Run the app
shinyApp(ui = ui, server = server)
This works; thank you @raytong. I will mark it as the solution within the next 24 hours.
Still, I'd like to understand why it is necessary to use the reactiveValues construct. What can't we just create a create a reactive df and update that object, like so below? (this also fails, but I can see that it is performing the row_bind. it just doesn't get updated in the renderTable):
library(shiny)
library(tidyverse)
ui <- fluidPage( tableOutput("timeTable") )
server <- function(input, output, session) {
#vals <- reactiveValues( time_accum = data.frame(time = NULL) )
time_accum <- reactive({ data.frame(time = as.character(Sys.time())) })
## the_time is a drop in replacement for reactiveFileReeader for this reprex
the_time <- reactive({
invalidateLater(1000, session)
data.frame(time = as.character(Sys.time()))
})
observe({
time <- the_time()
isolate( time_accum <- bind_rows(time_accum(), time) )
})
#vals$time_accum <- reactive( bind_rows(vals$time_accum, the_time()) )
output$timeTable <- renderTable( time_accum() )
}
shinyApp(ui = ui, server = server)
But it cannot assign a value to it. So, the script will not work.
time_accum <- bind_rows(time_accum(), time)
If you want to store a value, you have to use reactiveVal or reactiveValues. Using reactiveValues is my habit because it can store values like normal list object. You can use reactiveVal in your case but the readability of the script will be lower.
library(shiny)
library(tidyverse)
# DOESN"T WORK
# The UI
ui <- fluidPage( tableOutput("timeTable") )
server <- function(input, output, session) {
time_accum <- reactiveVal(data.frame(time = NULL) )
## the_time is a drop in replacement for reactiveFileReeader for this reprex
the_time <- reactive({
invalidateLater(1000, session)
data.frame(time = as.character(Sys.time()))
})
## the key step, which seems to be the fail point
observe(
{
time <- the_time()
isolate(time_accum(bind_rows(time_accum(), time)))
}
)
# vals$time_accum <- reactive( bind_rows(vals$time_accum, the_time()) )
output$timeTable <- renderTable( time_accum() )
}
# Run the app
shinyApp(ui = ui, server = server)