RShiny mainPanel按钮随input$n奇偶性异常行为求助
问题原因
- R语言懒求值特性导致循环创建
observeEvent时,所有监听器共享迭代变量的引用,最终取到的都是循环结束后的变量值,逻辑执行不符合预期 - 每次切换
input$n值时仅新增监听器,没有销毁旧监听器,同一个按钮ID对应多个监听器,触发时执行了之前n值对应的旧逻辑,操作了错误类别的排除列表,所以偶数n时点击按钮看起来没有响应 - 不同类别对应的按钮ID完全重复,进一步加剧了事件监听冲突
修复方法
核心修改点
- 按钮ID增加当前类别
n的标识,避免不同类别下的按钮ID重复 - 创建监听器时固定当前的
n和迭代变量i的取值,规避懒求值问题 - 给监听器添加自动销毁属性,切换类别后旧监听器自动清理,不会残留冲突
修改后的关键代码
1. 按钮ID修改(img_widget函数部分)
img_widget <- function(i) { if(input$n==0){ column(2, renderImage({ dispImgs(input$n,i) },outputArgs = c(height="200px") ) ) }else{ btn_id <- paste0("out_", input$n, "_", i) column(2, actionButton(btn_id, label = ifelse(excluded$ls[[input$n]][i],"Inclure","Exclure")), renderImage({ dispImgs(input$n,i) }, outputArgs = c(height="200px") ) ) } }
2. 监听器创建逻辑修改(observeEvent(input$n, ...)部分)
observeEvent(input$n,{ current_n <- input$n if(current_n == 0) return() # 类别为0时没有按钮不需要创建监听器 n_sample <- nrow(listDataMat[[current_n]]) lapply( X = 1:n_sample, FUN = function(i){ force(i) # 固定当前迭代的i值,规避懒求值问题 btn_id <- paste0("out_", current_n, "_", i) observeEvent(input[[btn_id]], { excluded$ls[[current_n]][i] <- !excluded$ls[[current_n]][i] updateActionButton(session, btn_id, label = ifelse(excluded$ls[[current_n]][i],"Inclure","Exclure")) print(excluded$ls[[current_n]]) }, autoDestroy = TRUE) # 切换n后旧监听器自动销毁,避免冲突 } ) })
额外注意
你初始化时仅生成了1~5类别的数据和排除列表,当input$n设置超过5时会报错,可根据自己的数据源调整Nsub参数的取值。
内容的提问来源于stack exchange,提问作者L Maxime
相关产品推荐
相关产品推荐

