title: How to add Vue 3 components programmatically?
body: <p>Vue 3 doesn't have Vue.extend() method, so example here doesn't work:
  <a href="https://css-tricks.com/creating-vue-js-component-instances-programmatically/" rel="noreferrer">https://css-tricks.com/creating-vue-js-component-instances-programmatically/</a></p>
  <p>I have tried this solution:
  <a href="https://jsfiddle.net/jamesbrndwgn/fsoe7cuy/" rel="noreferrer">https://jsfiddle.net/jamesbrndwgn/fsoe7cuy/</a></p>
  <p>But it causes warning in console:</p>
  <p><em>Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with <code>markRaw</code> or using <code>shallowRef</code> instead of <code>ref</code>.</em></p>
  <p><a href="https://i.stack.imgur.com/tzoYR.png" rel="noreferrer">enter image description here</a></p>
  <p>So, what is the proper way to add components dynamically (programmatically) in Vue 3?</p>
  <p>UploadTaskTagManager.vue</p>
  <pre><code>&lt;template&gt;
      &lt;button @click=&quot;addTag()&quot; type=&quot;button&quot;&gt;Add new tag&lt;/button&gt;
      &lt;br&gt;
      &lt;div&gt;
          &lt;div v-for=&quot;child in children&quot; :key=&quot;child.name&quot;&gt;
              &lt;component :is=&quot;child&quot;&gt;&lt;/component&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
      import UploadTaskTag from &quot;./UploadTaskTag&quot;;
  
      export default {
          name: &quot;UploadTaskTagManager&quot;,
          components: {UploadTaskTag},
  
          data() {
              return {
                  children: []
              }
          },
  
          methods: {
              addTag() {
                  this.children.push(UploadTaskTag);
              },
          }
      }
  &lt;/script&gt;
  </code></pre>
  <p>UploadTaskTag.vue</p>
  <pre><code>&lt;template&gt;
      &lt;div&gt;
          &lt;select @change=&quot;onChangeTag($event)&quot; v-model=&quot;currentTag&quot;&gt;
              &lt;option v-for=&quot;tag in getAllTags()&quot; :key=&quot;tag.tag_name&quot; :value=&quot;tag&quot;&gt;{{tag.tag_name}}&lt;/option&gt;
          &lt;/select&gt;
          &lt;input maxlength=&quot;16&quot; class=&quot;tag-input&quot; ref=&quot;inputField&quot;/&gt;
          &lt;button @click=&quot;removeTag($event)&quot; type=&quot;button&quot;&gt;-&lt;/button&gt;
          &lt;br&gt;
      &lt;/div&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
      export default {
          name: &quot;UploadTaskTag&quot;,
  
          data() {
              return {
                  tags: [],
                  currentTag: {}
              }
          },
  
          methods: {
              onChangeTag(event) {
                  this.$refs.inputField.value = this.currentTag.tag_name;
              },
  
              getAllTags() {
                  return this.$store.state.allTags;
              },
  
              removeTag() {
                  this.$el.parentElement.removeChild(this.$el)
              },
  
              getValue(fieldIndex) {
                  let tag = this.tags[fieldIndex];
                  return tag ? tag.tag_name : &quot;&quot;;
              },
          }
      }
  &lt;/script&gt;
  </code></pre>