Reputation: 1
I'm building my first Shiny app and I'm running into some trouble.
When I register a new user for the app, I need to add a row with some empty values to a dataframe, that will be used to generate recommendations.
user_features3 <- rbind(user_features3,c(612,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0))
This works alright while the app isn't running, and the 612th row is added. But while it's running, this has no effect on user_features3. I think this may be because R is busy with the webapp.
If I make a reactive value, say values <- reactiveValues() and then
value$df <- user_features3
, I can modify the values in this reactive one, but I am unable to access the non-reactive one in a similar manner while the app is running.
I need to update it in real-time so that I can use it to generate movie recommendations. Any suggestions?
Upvotes: 0
Views: 673
Reputation: 161085
This solves your asked question, but modifying non-reactive variables can cause problems as well. In general, thinking about modifying a non-reactive variable within a shiny
environment indicates perhaps you aren't thinking about how to scale or store or properly maintain the app state. For instance, if you are expecting multiple users, then know that this data is not shared with the other users, it is the current-user only. There is no way around this using local variables. (If you need to "share" something between users, you really need a data backend such as some form of SQL, including SQLite. See: https://shiny.rstudio.com/articles/persistent-data-storage.html)
In addition to all of the other shiny
tutorials, I suggest you read about variable scope in shiny, specifically statements such as
server
function definition;server
function; andglobal.R
are similar to those defined in app.R
outside of the server function definition".Having said that, two offered solutions.
library(shiny)
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
textInput(inputId = "sometext", label = "Some Text:",
placeholder = "(nothing meaningful)"),
actionButton(inputId = "addnow", label = "Add!")
),
mainPanel(
tableOutput("myframe")
)
)
)
server <- function(input, output, session) {
rxframe <- reactiveVal(
data.frame(txt = character(0), i = integer(0),
stringsAsFactors = FALSE)
)
observeEvent(input$addnow, {
newdat <- data.frame(txt = isolate(input$sometext),
i = nrow(rxframe()) + 1L,
stringsAsFactors = FALSE)
rxframe( rbind(rxframe(), newdat, stringsAsFactors = FALSE) )
})
output$myframe <- shiny::renderTable( rxframe() )
}
shinyApp(ui, server)
This example uses shiny::reactiveVal
, though it would be just as easy to use shiny::reactiveValues
(if multiple reactive variables are being used).
library(shiny)
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
textInput(inputId = "sometext", label = "Some Text:",
placeholder = "(nothing meaningful)"),
actionButton(inputId = "addnow", label = "Add!")
),
mainPanel(
tableOutput("myframe")
)
)
)
server <- function(input, output, session) {
nonrxframe <- data.frame(txt = character(0), i = integer(0),
stringsAsFactors = FALSE)
output$myframe <- shiny::renderTable({
req(input$addnow)
nonrxframe <<- rbind(nonrxframe,
data.frame(txt = isolate(input$sometext),
i = nrow(nonrxframe) + 1L,
stringsAsFactors = FALSE),
stringsAsFactors = FALSE)
nonrxframe
})
}
shinyApp(ui, server)
Both allow sequencing as the screenshots below demonstrate. Many will argue that the first (reactive) example is cleaner and safer. (Just the use of <<-
is deterrent enough for me!)
Upvotes: 2