Search code examples
rtwittershinyhtmlwidgetstwitter-widget

R twitterwidget package - tweet not cleared when shiny input is updated


Each time my input to renderTwitterwidget() is changed, a new tweet is printed underneath the original tweet on the Shiny UI. Is it possible to clear the old tweet and print a new one each time a new twitterwidget object is passed to renderTwitterwidget?

Example of the problem: https://media.giphy.com/media/BQUewH12DzhxX2bjMP/giphy.gif?cid=790b7611692336f45990123a77213a1975b8338b7e69b6e1&rid=giphy.gif&ct=g

The code doesn't properly render the content using the RStudio viewer, so please use view the app in the browser to check the result.

This is the code for the shiny app:

# Libraries ---------------------------------------------------------------

library(shiny)
library(twitterwidget)
library(tidyverse)
library(rtweet)

# UI ----------------------------------------------------------------------

ui <- fluidPage(
  # Input functions
  textInput(inputId = 'search_term',
            label = 'Search tweets from the last 6-9 days:',
            #value = 'covid',
            placeholder = '#covid-19',
            width = '90%'
  ),
  actionButton(inputId = 'submit_button',
               label = 'Submit'
  ),
  
  # Output functions 
  twitterwidgetOutput('twitter', width = "100%", height = "400px")
)

# Server ------------------------------------------------------------------

server <- function(input, output) {
  
  # Get data 
  tweet_id <- eventReactive(input$submit_button, {search_tweets(q = input$search_term, n = 1, lang = 'en') %>% pull(status_id)})
 
  # Twitter widget
  output$twitter <- renderTwitterwidget(twitterwidget(tweet_id()))
  
}

shinyApp(ui, server)

Code for those without a twitter account:

# Libraries ---------------------------------------------------------------

library(shiny)
library(twitterwidget)
library(tidyverse)


# Vector of tweet status_id's ---------------------------------------------

v_ids <- c("1434550715905724416", "1434404394133594112", "1434270392533889039", "1432293982541946884", "1432396306698354688",
           "1434187565633003526", "1433095963338551297", "1432339458309955585", "1431909314600574977","1432064144040202241",
           "1434268168231477248", "1431912031100227589", "1434188285103022086", "1432066801588920325", "1434184994579230720",
           "1434100772069908485", "1433887544274563075", "1433801716202344460", "1433799487592468492", "1433754869429592078",
           "1433120347176386561", "1432410673259057161", "1433115345938784263", "1433093342456389639", "1432961860731478017",
           "1432828362280476673", "1432812324709179394", "1432806681793159168", "1432721292403281920", "1432707208211537930",
           "1432700115299586053", "1432658875665289216", "1432623112747638785", "1432614035141312513", "1432612768717451266")

# UI ----------------------------------------------------------------------

ui <- fluidPage(
  # Input functions
  textInput(inputId = 'search_term',
            label = 'Search tweets from the last 6-9 days:',
            #value = 'covid',
            placeholder = '#covid-19',
            width = '90%'
  ),
  actionButton(inputId = 'submit_button',
               label = 'Submit'
  ),
  
  # Output functions 
  twitterwidgetOutput('twitter', width = "100%", height = "400px")
)

# Server ------------------------------------------------------------------

server <- function(input, output) {
  
  # Get data 
  tweet_id <- eventReactive(input$submit_button, {sample(v_ids, 1)})
 
  # Twitter widget
  output$twitter <- renderTwitterwidget(twitterwidget(tweet_id()))
  
}

shinyApp(ui, server)

Solution

  • Weird functionality, not sure if its an issue with the package or what. You can also just use shinyjs and write a user-defined javascript function to clear the contents of the div.

    Here is a brief implementation that should work:

    # Libraries ---------------------------------------------------------------
    
    library(shiny)
    library(twitterwidget)
    library(tidyverse)
    library(rtweet)
    
    # UI ----------------------------------------------------------------------
    
    ui <- fluidPage(
      shinyjs::useShinyjs(),
      shinyjs::extendShinyjs(
        text = "shinyjs.refresh = function() {
          var div = document.getElementById('twitter_output');
          while(div.firstChild){
              div.removeChild(div.firstChild);
            }
          }",
        functions = c("refresh")
      ),
      # Input functions
      textInput(
        inputId = 'search_term',
        label = 'Search tweets from the last 6-9 days:',
        #value = 'covid',
        placeholder = '#covid-19',
        width = '90%'
      ),
      actionButton(inputId = 'submit_button',
                   label = 'Submit'),
      
      twitterwidgetOutput("twitter_output")
    )
    
    # Server ------------------------------------------------------------------
    
    server <- function(input, output) {
      observeEvent(input$submit_button, {
        # Obtain tweet ID
        tweet_id <-
          search_tweets(q = input$search_term,
                        n = 1,
                        lang = 'en') %>%
          pull(status_id)
        
        # Refresh the `twitter_output` div
        shinyjs::js$refresh()
        
        # Render the tweet again.
        output$twitter_output <-
          renderTwitterwidget(twitterwidget(tweet_id))
      })
    }
    
    shinyApp(ui, server)