Я динамически создаю элементы для вставки в fluidRow
, проблема, с которой я сталкиваюсь, заключается в том, что все элементы визуализируются одновременно. Таким образом, вместо того, чтобы отображать каждый элемент, когда его renderUI
функция заканчивается, все они продолжают ждать, пока не завершится последний renderUI
. Таким образом, наличие большого количества элементов в my_dataset
делает рендеринг очень медленным.
Я ожидал, что после отображения print(str_glue('End: {i}'))
элемент будет отрисован. Однако это было не так, он ждал всех элементов (в том числе и тех, которые не были видны на экране).
Я пытался использовать outputOptions(..., suspendWhenHidden = TRUE)
, но это не имело значения (как и ожидалось, поскольку это значение по умолчанию).
MWE
library(shiny)
library(shinydashboard)
library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
library(shinycssloaders)
qtd <- 500
my_dataset <- data.frame(
stringsAsFactors = F,
Name = rep('Sample', qtd),
Value = runif (qtd)
)
ui <- function() {
fluidPage(
fluidRow(
column(12, textInput(inputId = 'my_text_input', label = NULL, placeholder = 'Search', width = '100%')),
uiOutput('custom_ui')
)
)
}
server <- function(input, output, session) {
output[['custom_ui']] <- renderUI({
filtered_dataset <- my_dataset %>%
filter(grepl(input[['my_text_input']], Name, ignore.case = T)) %>%
arrange(Name)
map(1:nrow(filtered_dataset), function(i) {
item <- filtered_dataset[i,]
custom_id <- str_glue('custom_id_{i}')
output[[custom_id]] <- renderUI({
print(str_glue('Start: {i}'))
print(item)
result <- box(
width = 3,
title = item$Name,
item$Value
)
print(str_glue('End: {i}'))
result
})
column(width = 3, uiOutput(custom_id, style = 'height: 350px;') %>% withSpinner(type = 6))
})
})
}
runApp(shinyApp(ui = ui, server = server), launch.browser = T)
@Limey Я добавил MWE
То, что вы описываете, является ожидаемым поведением. Сервер ничего не вернет пользовательскому интерфейсу, пока все вычисления не будут завершены.
Я вижу, вы очень полагаетесь на renderUI
. Это делает приложение Shiny медленным. Когда приложение запускается, оно должно загрузиться, понять, что ему не хватает части пользовательского интерфейса, попросить сервер создать пользовательский интерфейс, после чего сервер создаст HTML-код для всех ваших полей и отправит их в пользовательский интерфейс до того, как что-либо будет показано. Вы должны попытаться сохранить как можно больше статичного пользовательского интерфейса.
В зависимости от того, чего вы хотите достичь, вероятно, есть много разных способов сделать это без renderUI
.
Ниже приведен пример, в котором HTML-код для блоков создается вне renderUI
. Это будет работать, если вам не нужны элементы управления вводом или выводами в полях, потому что тогда им нужен собственный идентификатор.
library(shiny)
library(shinydashboard)
library(dplyr)
library(purrr)
qtd <- 500
my_dataset <- data.frame(
stringsAsFactors = FALSE,
Name = rep('Sample', qtd),
Value = runif (qtd)
) %>%
mutate(
x = map2(
Name,
Value,
~column(
width = 3,
box(
width = 3,
title = .x,
.y
)
)
)
)
ui <- function() {
fluidPage(
fluidRow(
column(
12,
textInput(
inputId = 'my_text_input',
label = NULL,
placeholder = 'Search',
width = '100%'
)
),
uiOutput('custom_ui')
)
)
}
server <- function(input, output, session) {
# Only the filtering of the data is done inside `renderUI`
output[['custom_ui']] <- renderUI({
filtered_dataset <-
my_dataset %>%
filter(grepl(input[['my_text_input']], Name, ignore.case = TRUE)) %>%
arrange(Name) %>%
pull(x)
})
}
runApp(shinyApp(ui = ui, server = server), launch.browser = TRUE)
Last I just want to recommend this book by Hadley Wickham. I think reading this (or parts of this) book before working with Shiny will make everything easier for you.
Спасибо за ответ и за справочник, посмотрю! Ваше решение действительно работает как шарм для де MWE, который я выложил, но, к сожалению, для моей реальной проблемы это не так =/. Как вы прокомментировали, у меня есть некоторые выходы, которые мне нужно установить там динамически, но не волнуйтесь! Я уже нашел обходной путь для моей проблемы, который сработал для меня =). Еще раз, спасибо за ваше время!
Вы не дали нам MWE, поэтому трудно быть уверенным, но...
renderUI
— это функция. Он вернется только после того, как весь содержащийся в нем код будет выполнен. Следовательно, вы ничего не видите, пока не увидите все. Варианты повышения скорости: (1) перенести построение набора данных за пределы renderUI. (Это хорошая практика, и я подозреваю, что вам все равно придется это делать.) 2 Поскольку вы фактически дублируете один и тот же интерфейс (с разными данными), определите модуль для представления интерфейса и создайте несколько экземпляров модуля для отображения. различные сокращения данных.