r - 防止使用两个依赖路径双重执行闪亮的反应
问题描述
考虑以下闪亮的应用程序。用户可以更改三个基本输入:A
、M
和S
。“内容” C(在verbatimTextOuput
右侧)直接取决于A
和S
。
S
可以通过两种方式进行更改:由用户或通过更改M
/ A
。如果用户改变了S
,那么依赖就M
无关紧要了。M
如果为空,也不会使用。
情况如下图所示。
问题是 whenM
不是空白并且A
被更改:
C
根据新旧S
更新A
S
更新基于M
和新的A
C
根据 newS
和 new得到更新A
。
因此,C
更新两次,第一次使用无效值。
我想要发生的是S
基于 new进行更新A
,然后C
基于 newS
和 new进行更新A
。
要查看问题,请运行应用程序,然后:
- 把东西放进
M
盒子里 - 改变
A
- 观察到
C
改变了两次。
如何阻止第一次更新?
谢谢!
闪亮的应用程序代码:
library(shiny)
library(digest)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
textInput("M", "M:", ""),
textInput("S", "S:", "testS"),
selectInput("A", "A:", c("A1","A2"))
),
mainPanel(
verbatimTextOutput("C")
)
)
)
server <- function(input, output, session) {
# Count calculations of C
count = 0
# Make reactive so we can modify the value
# in the input box (inpt$S is an input and output,
# essentially)
S <- reactive({
input$S
})
# Create "content" from A and S
C <- reactive({
count <<- count + 1
Sys.sleep(0.5)
message("Count ", count)
paste(
"Count: ", count, "\n", digest::sha1( c(input$A, S()) )
)
})
# When M changes, we need to change S based on A and M
# OR set S to a default value
observeEvent(input$M, {
# If user gets rid of M, reset S to default
if(input$M == ""){
S = "testS"
}else{
S = digest::sha1(c(input$M,input$A))
}
# Update the input to new S
updateTextInput(
session,
"S",
value = S
)
})
# When A changes, we need to change S based on A and M
# OR if M is blank, do nothing (S doesn't depend on M if M is blank)
observeEvent(input$A, {
# If there's no M, don't use it
if(input$M == "") return()
# Update the input to new S
updateTextInput(
session,
"S",
value = digest::sha1(c(input$M,input$A))
)
})
# "Content"
output$C <- renderText({
C()
})
}
shinyApp(ui = ui, server = server)
解决方案
我认为这里的问题是当你应该使用反应器时你正在使用观察者。通常,您只想使用观察者来获得副作用(保存文件,按下按钮),而不是在您想要应用程序中的值时。在这里,我认为最好使用renderUI
响应式生成 UI 元素,而不是使用观察者更新它。
library(shiny)
library(digest)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
textInput("M", "M:", ""),
uiOutput("S_UI"),
selectInput("A", "A:", c("A1","A2"))
),
mainPanel(
verbatimTextOutput("C")
)
)
)
server <- function(input, output, session) {
# Count calculations of C
count = 0
# Create "content" from A and S
C <- reactive({
count <<- count + 1
Sys.sleep(0.5)
message("Count ", count)
paste(
"Count: ", count, "\n", digest::sha1( c(input$A, input$S ))
)
})
output$S_UI <- renderUI({
if (input$M == "") {
val <- "testS"
} else {
val <- "S"
}
return(textInput("S", "S:", val))
})
# "Content"
output$C <- renderText({
C()
})
}
shinyApp(ui = ui, server = server)
推荐阅读
- deep-learning - 词级语言模型的准确率极差,每个 epoch 的训练时间长
- micrometer - micrometer.io 的“NOOPd”是什么意思?
- protobuf-net - 我面临一个问题。我想以protobuf格式转换数据表数据。我的表返回我这样的列
- html - 将背景图像添加到 SVG
- amazon-ecs - 使用多个服务在 ECS 上部署 docker-compose 文件
- javascript - 使用 setState 使用输入值更新处于本地状态的对象项的值
- android - 如何下载适用于 Android 的 Xbox-live SDK 包?
- .htaccess - 误解从旧域重定向到新域的工作原理
- python - 如何以正确的方式在 python 中使用 flatbuffers?
- python - 搜索不同字符的索引