Это решает ваш заданный вопрос, но изменение нереактивных переменных также может вызвать проблемы.В целом, размышления об изменении нереактивной переменной в среде shiny
указывают на то, что, возможно, вы не задумываетесь о том, как масштабировать, хранить или правильно поддерживать состояние приложения.Например, если вы ожидаете нескольких пользователей, то знайте, что эти данные не передаются другим пользователям, это только текущий пользователь.Обойти это невозможно, используя локальные переменные.(Если вам нужно «поделиться» чем-то между пользователями, вам действительно необходим сервер данных, такой как SQL, включая SQLite. См .: https://shiny.rstudio.com/articles/persistent-data-storage.html)
В дополнение ко всем другим shiny
учебным пособиямЯ предлагаю вам прочитать о переменной области действия в блестящем, в частности, такие заявления, как
- "Набор данных только для чтения, который будет загружен один раз, когда Shiny запускается и будет доступен для каждого сеанса пользователя ", говоря о данных, хранящихся вне определения функции
server
; - " Эта локальная копия [этой переменной]не быть видимым в других сеансах ", говоря о переменной, хранящейся в функции
server
; и - " Объекты, определенные в
global.R
, аналогичны тем, которые определены в app.R
снаружиопределения серверной функции ".
Сказав это, два предложенных решения.
Reactive Frame (приветствуется!)
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)
Этот примериспользует shiny::reactiveVal
, хотя было бы просто использовать shiny::reactiveValues
(если используются несколько реактивных переменных).
Нереактивный фрейм (не рекомендуется)
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)
Обе позволяют выполнять последовательность, как показано на скриншотах ниже.Многие утверждают, что первый (реактивный) пример чище и безопаснее.(Только использование <<-
является достаточным сдерживающим фактором для меня!)
![steps of adding data to the non-reactive frame](https://i.stack.imgur.com/qxEf8.png)