Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shinylive problem #1

Open
timelyportfolio opened this issue Jul 18, 2024 · 1 comment
Open

shinylive problem #1

timelyportfolio opened this issue Jul 18, 2024 · 1 comment

Comments

@timelyportfolio
Copy link

See ramnathv/htmlwidgets#487 for reference and background. @jcheng5 @seanbirchall

Debugging shinylive

Since MessageChannel replaces traditional Shiny websocket (easily tracked in browser debugging tools) in shinylive/webR, debugging can be a little more difficult. I discovered

  1. options(shiny.trace = TRUE) in the app will log to browser console which is helpful
  2. manually hacking shinylive-inject-socket.txt around line[https://github.com/posit-dev/shinylive/blob/main/src/assets/shinylive-inject-socket.txt#L62] by adding if(event.value && event.value.data) {console.log(JSON.parse(event.value.data))} after shinylive::export() in shinylive-sw.js provides the full stream

Potential Partial Solution (at least locally for me in shinylive)

While this helps in my local testing, I want to stress that the issue still eventually will appear if viewer is not cleared after first render. Before I was not able to get any rendered df_viewer, but it sounds like in the original issue that df_viewer would appear.

Moving lines to the end of mod_df_viewer.R seems to partially resolve what appears to be an asynchrony issue that happens in the shinylive context. Oddly, when I added a line before the req (even a commented one) without changing the order of the code, then the problem also went away at least locally in a shinylive context.

Sean, if working correctly, you should be able to remove the manually added dependencies in lines.

Problem

The shiny::req(ide$environment_selected, input$index, input$rows, input$columns) in line leads to a null data message sent. Then htmlwidgets line fails since data.deps does not exist.

image

@seanbirchall
Copy link
Owner

This helps, was cluelessly debugging shinylive apps previously.

I just finished a partial workaround, but I lose the ability to persist widgets in the viewer. Should be able to add some additional reactiveValues to fix it though.

Combination of debouncing my renderdfViewer and setting ide$viewer to NULL whenever the user swaps between viewer and environment pane.

mod_df_viewer.R

      output$spreadsheet <- renderdfViewer({
        shiny::req(ide$environment_selected, input$index, input$rows, input$columns)
        df <- ide$environment_selected
        # Logic for start index
        start_index <- as.integer(input$index)
        if(is.na(start_index) | start_index < 1){
          start_index <- 1
        }else if (start_index > nrow(df)){
          start_index <- nrow(df)
        }

        # Logic for rows
        row_count <- as.integer(input$rows)
        if(row_count > 0){
          # View first n rows
          end_index <- min(start_index + row_count - 1, nrow(df))
          df <- df[start_index:end_index, , drop = FALSE]
        }else{
          # View last n rows
          start_index <- max(1, nrow(df) + row_count + 1)
          df <- df[start_index:nrow(df), , drop = FALSE]
        }

        # Logic for columns
        col_count <- as.integer(input$columns)
        if (col_count > 0) {
          # View first n columns
          df <- df[, 1:min(col_count, ncol(df)), drop = FALSE]
        } else {
          # View last n columns
          col_start <- max(1, ncol(df) + col_count + 1)
          df <- df[, col_start:ncol(df), drop = FALSE]
        }

        if(is.null(df)){
          df <- data.frame()
        }

        df_viewer(
          data = df,
          colHeaders = names(df),
          width = "100%"
        )
      }) |>
        debounce(1000)

control.R

      shiny::observeEvent(input$tab_environment, {
        ide$viewer <- NULL
        ide$tab_control <- "environment"
      })

So I should get a working solution that keeps the app functioning as I want so long as I flag for when the user is trying to view data using the df_viewer widget. In other instances when the user runs code with an htmlwidget (reactable, gt, ggplot, listviewer... small list for now). Another issue for another day to programmatically detect widgets, wrap them in their render function, and then rerun. Need to look more into how George is doing widgets in his R repl app, as the rerun might be unnecessary at this point.

Thanks again @timelyportfolio!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants