title: R Shiny: "Error in $.shinyoutput: Reading from shinyoutput object is not allowed."
body: <p>I'm making a shiny app in which the user can generate tabs that display different dataframes based on the number of tabs made. For example, in the code below:</p>
  
  <pre><code>library(shiny)
  library(shinythemes)
  library(DT)
  
  ui &lt;- navbarPage(theme = shinytheme("flatly"), 
                   title = "",
                   id = "tabs",
                   position = "static-top",
                   tabPanel(title = "Plus",
                            icon = icon("plus"))
  )
  
  
  server &lt;- function(input, output, session) {
  
    count &lt;- reactiveValues(value = 0)
  
    observeEvent(input$tabs, {
      if (input$tabs == "Plus"){
        count$value &lt;- count$value + 1
        id = paste0("Base ", count$value)
        insertTab(inputId = "tabs",
                  tabPanel(title = id,
                           fluidRow(
                             column(width = 12,
                                    dataTableOutput(outputId = paste0("data", count$value))
                             )
                           )), target = "Plus", 
                  position = "before",
                  select = TRUE)}
    })
  
  
      output$data1 &lt;- renderDataTable({
        mtcars[1, 1:2]
      })
  
  
      output$data2 &lt;- renderDataTable({
        mtcars[2, 1:2]
      })
  
  
      output$data3 &lt;- renderDataTable({
        mtcars[3, 1:2]
      })
  
  }
  
  shinyApp(ui = ui, server = server)
  </code></pre>
  
  <p>you can see that the user can add a tab and that tab 1 will generate the first row of the dataframe, tab 2 the second row of the dataframe, etc.</p>
  
  <p>However, there is a limit to this method: I have to write the code for all rows that the user can potentially display. In order to reduce the length of the code while not limiting the user to a certain number of rows, I would like to automate that.</p>
  
  <p>I would like to create a function that will display the right row in each tab. Therefore, I make a function that creates a different dataframe given its argument and I include this function in <code>observeEvent</code>, so that clicking on "Plus" creates a new tab and fills it with the right dataframe. </p>
  
  <p>Below is the new code (the <code>ui</code> part is the same):</p>
  
  <pre><code>server &lt;- function(input, output, session) {
  
    treat &lt;- function(i){
      output$paste0("data", i) &lt;- renderDataTable({
        mtcars[i, 1:2]
      })
    }
  
    count &lt;- reactiveValues(value = 1)
  
    observeEvent(input$tabs, {
      if (input$tabs == "Plus"){
        count$value &lt;- count$value + 1
        id = paste0("Base ", count$value)
        insertTab(inputId = "tabs",
                  tabPanel(title = id,
                           fluidRow(
                             column(width = 12,
                                    dataTableOutput(outputId = paste0("data", count$value))
                             )
                           )), target = "Plus", 
                  position = "before",
                  select = TRUE)
  
        treat(count$value)
        }
    })
  </code></pre>
  
  <p>The problem is that I get this error: </p>
  
  <blockquote>
    <p>Error in &lt;-: target of assignment expands to non-language object</p>
  </blockquote>
  
  <p>Searching for solutions, I find that I need to use the <code>assign</code> function. So I change my function to:</p>
  
  <pre><code>  treat &lt;- function(i){
      assign(output$paste0("data", i), renderDataTable({
        mtcars[i, 1:2]
      })
      )
    }
  </code></pre>
  
  <p>But since I am now using a shiny output in a function, I have the error:</p>
  
  <blockquote>
    <p>Error in $.shinyoutput: Reading from shinyoutput object is not allowed.</p>
  </blockquote>
  
  <p>How could I bypass this error to obtain what I want?</p>