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

Custom render function firing multiple times #357

Open
dleopold opened this issue Feb 12, 2024 · 3 comments
Open

Custom render function firing multiple times #357

dleopold opened this issue Feb 12, 2024 · 3 comments

Comments

@dleopold
Copy link

I was debugging a custom render function for a table inside a shiny app and noticed that updates to the table cause the function to fire 3 x for each row on every render. The rendered table is correct, it just appears that the function is firing more times than it should need to. Not sure if this is a bug or just an unavoidable side effect of how the table is rendered. Here is a simple shiny app with a console.log() call added in the render function so you can see how many times it fires in the browser console.

library(shiny)
library(reactable)

ui <- fluidPage(
  reactableOutput("table"),
  actionButton("update", "Update table")
)

server <- function(input, output) {
  
  tabDat <- reactiveVal(iris[1:2,])
  
  output$table <- renderReactable({
    reactable(
      tabDat(),
      columns = list(
        Species = colDef(
          html = TRUE,
          cell = htmlwidgets::JS(
            "
            function(cellInfo) {
              console.log(cellInfo.value)
              return 'cellInfo.value';
            }
            "
          )
        )
      )
    )
  })
  observeEvent(input$update, {
    tabDat(iris[sample(1:nrow(iris), 2), ])
  })
}
shinyApp(ui = ui, server = server)
@glin
Copy link
Owner

glin commented Feb 20, 2024

This is just a technical limitation in react-table that allows some essential functionality to work, and is not real easy to avoid right now. Fortunately there are only a few cases where a table will render multiple times at once. Initial render is the worst at 3 times, but paginating, sorting, filtering, etc. usually just trigger one rerender.

Render functions aren't meant to be heavyweight or fire off their own side effects, so it's been fine for now, I think you've been the only one to notice. Maybe one day this could be improved? But it'd be a lot of effort to rework table internals, so not a priority right now.

edit: I forgot to mention, another mitigation for this would be to debounce consecutive custom render function calls so that 3 rapid fires get collapsed down to just 1. reactable is already doing this in some places to deal with the multiple rerendering limitation.

@dleopold
Copy link
Author

Thanks for the feedback. I am not sure I follow the method you suggest in you edit. Could you elaborate? How would you do that in the example in my post?

@dleopold
Copy link
Author

I was just doing some testing on this and noticed that (for this example at least) sorting causes the render function to fire 2x, but updating the data with updateReactable() actually causes it to fire 5x for each cell! That seems like a lot of unnecessary function calls. I attempted to debounce the function without any success so far.

library(shiny)
library(reactable)

ui <- fluidPage(
  reactableOutput("table"),
  actionButton("update", "Update table")
)

server <- function(input, output) {
  
  output$table <- renderReactable({
    reactable(
      iris[1:2,],
      columns = list(
        Species = colDef(
          html = TRUE,
          sortable = TRUE,
          cell = htmlwidgets::JS(
            "
            function(cellInfo) {
              console.log(cellInfo.value)
              return 'cellInfo.value';
            }
            "
          )
        )
      )
    )
  })
  observeEvent(input$update, {
    updateReactable(
      "table",
      data = iris[sample(1:nrow(iris), 2), ]
    )
  })
}
shinyApp(ui = ui, server = server)

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