Here's a working shiny app to allow arbitrary QR generate (of text), showing in both SVG and PNG.
library(shiny)
ui <- fluidPage(sidebarLayout(
  sidebarPanel(
    textInput("text", label = NULL, placeholder = "(some phrase)"),
    imageOutput("svgplot")
  ),
  mainPanel(
    plotOutput("plot")
  )
))
server <- function(input, output, session) {
  QR <- eventReactive(input$text, {
    qrcode::qr_code(input$text)
  })
  output$svgplot <- renderImage({
    txt <- isolate(input$text)
    tf <- tempfile(fileext = ".svg")
    qrcode::generate_svg(QR(), tf, size = 100, foreground = "black", background = "white", show = FALSE)
    list(
      src = normalizePath(tf),
      contentType = "image/svg+xml",
      width = 100, height = 100,
      alt = paste("My QR code:", sQuote(txt, FALSE))
    )
  }, deleteFile = TRUE)
  output$plot <- renderPlot({ plot(QR()) })
}
shinyApp(ui, server)

You don't need to show both, I thought I'd compare/contrast how to show them since they require different steps.
Key takeaways:
- renderImageallows us to show an arbitrary image that the browser should support. The expression in this call must be a- listwith the attributes for the HTML- imgattribute, so here my- list(...)is creating
 - <img src="path/to/tempfile.svg" contentType="image/svg+xml" width=100 height=100 alt="...">
 
- I'm doing a two-step here: create the QR object as reactive data, and then anything that will use that will depend on - QR()(my QR object). This way there will be fewer reactive-chain calls. This may not be strictly necessary if all you're doing is showing a single QR code, over to you.
 
- shiny::renderImagerequires the- deleteFile=argument; if all you want to is show it, this is fine; if the user wants to right-click on the displayed SVG file and download it locally, it's still fine. In fact, since the "link" text is- data:image/svg+xml;base64,PD94bWwgdmVy...and is a fairly long string (39K chars in one example), even if the temp file is deleted, this link remains unchanged and working.