Loading dynamic components asynchronously in Vue 3 allows for improved performance and enhanced user experience

My goal is to dynamically display components based on their type. Here's how I'm approaching it:

I have several similar components that should show different content depending on their type. Using the defineAsyncComponent method, I can easily import and use these components. For example:

const CheckBoxControl = defineAsyncComponent(
  () => import('@/components/editor/controls/CheckBoxControl.vue'),
);

While this method works fine, I end up with a long list of imported components, which is not ideal. To address this, I've wrapped the defineAsyncComponent inside an arrow function like so:

const loadComponent = async (type: string) =>
  defineAsyncComponent(
    () =>
      import(
        `@/components/editor/controls/${type[0].toUpperCase()}${type.substring(
          1,
        )}Control.vue`
      ),
  );

In the template, I can then render the component using

<component :is="renderComponent(control.type)" />

However, this approach triggers the following warning: "[Vue warn]: Component is missing template or render function." Even awaiting the defineAsyncComponent method doesn't resolve the issue.

What am I doing wrong? How can I dynamically import and render these components?

Update

These are the possibilities for the control.type attribute:

  • checkbox
  • date
  • email
  • number
  • radio
  • range
  • select
  • textarea
  • text

Update 2

Here is my current code that is functioning correctly:

const CheckBoxControl = defineAsyncComponent(
  () => import('@/components/editor/controls/CheckBoxControl.vue'),
);

// Repeat above pattern for other control types

const loadComponent = (type: string) => {
  switch (type) {
    case 'checkbox':
      return CheckBoxControl;
    // Add cases for other control types here
  }
};

Update 3

My setup involves using Vite as the build tool, version 2.9.5. I'm also using Vue version 3.2.33 and TypeScript version 4.6.3.

Answer №1

Big thanks to @Estus Flask for the assistance :)

The issue I encountered was due to my attempt to import it using the @ alias. The solution came when I revised my approach like so:

const loadComponent = (type: string) =>
  defineAsyncComponent(
    () =>
      import(
        `./controls/${type[0].toUpperCase()}${type.substring(1)}Control.vue`
      ),
  );

This adjustment resolved the problem.

I'm puzzled as to why the @ alias didn't work in this scenario, especially since it functions correctly in

const CheckboxControl = defineAsyncComponent(
  () => import('@/components/editor/controls/CheckboxControl.vue'),
);

If anyone can shed light on this discrepancy, it would be greatly appreciated.

Answer №2

async requires the function to return a promise object, but in this case a component is needed. It should be a standard function:

const createComponent = (type: string) => ...

The correct way to handle promises from import is using defineAsyncComponent.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Emphasize a word in a Typescript text by wrapping it in an HTML tag

I've been experimenting with using HTML tags within TypeScript to highlight specific words in a sentence before displaying the sentence in HTML. Despite searching on StackOverflow for various solutions, I haven't been able to find one that works. ...

Exploring Nuxt's Getters with vuex-class for seamless data retrieval

Currently, I am in the process of developing an application using Nuxt and experimenting with vuex for the first time. Despite following numerous tutorials to set it up, I'm encountering difficulties accessing the store and suspect that the issues may ...

Steps for setting up i18nextStart by including the i

I am working on developing a multilingual app using the i18next package. Unfortunately, I am experiencing issues with the functionality of the package. Below is an example of the i18next file I have been using: import i18n from "i18next"; impor ...

What are the steps to activating components in vue.js?

Why do I always see the UsersList.vue component when opening any URL? Is it because I include it in the App.vue? If I change it to <router-view/>, I only see an empty page. How can I resolve this issue? Also, how can I navigate from ListView to Detai ...

The React useEffect() hook causing an infinite re-render when trying to fetch all data regardless of

Recently, I've begun diving into React and utilizing the useEffect hook to fetch news and events from a database upon page load. However, when attempting to add a loading spinner, I encountered an unexpected infinite loop issue that has left me scratc ...

Discovering the right category for a general component: A step-by-step guide

How about creating a new list component that can work with an array of objects? <script setup lang="ts"> const props = defineProps<{ items: Record<string, unknown>[], selected: Record<string, unknown> | null field: stri ...

Converting a string value into an object in Javascript using a command that functions similarly to eval in Python

When working with Python, the stringValue variable is often assigned as a string: stringValue = '{"DATA":{"VERSION":1.1, "STATE":True, "STATUS":"ONLINE"}}' To convert this string into a Python di ...

Step-by-step guide for deploying an Angular 2 CLI app on GitHub

As a front-end engineer, I have limited experience with deployment. Currently, I am working on my pet project using angular-cli. What is the best way to deploy it on GitHub Pages? Are there any other straightforward methods for deployment? ...

How come only a single field is getting assigned when a new document is generated in Firebase, despite passing in multiple fields?

I’m in the process of generating a document within my "Users" collection that contains various fields (such as role, email, createdAt). I have these fields and their corresponding data stored in a "data" variable, and I’m setting the document to that o ...

Angular Delight: Jaw-Dropping Animation

After setting up my first Angular project, I wanted to incorporate Angular Animations to bring life to my content as the user scrolls through the page. I aimed to not only have the content appear on scroll but also implement a staggering animation effect. ...

Troubleshooting issue with Vue Class Component and Vuex-class causing ESLint error

I am interested in utilizing vuex-class to bind helpers for vuex and vue-class-component However, an error message is displayed: Error: Parsing error - Using the export keyword between a decorator and a class is not allowed. Please use `export @dec class ...

"Exploring the TypeScript typing system with a focus on the typeof operator

My goal is to create a function that will return the typeof React Component, requiring it to adhere to a specific props interface. The function should return a type rather than an instance of that type. Consider the following: interface INameProps { ...

What is causing the subscriber to receive the error message "Cannot access 'variable' before initialization" while referencing itself?

Within my Angular 8 project, I have a component that is dependent on a service for data loading. It waits for a notification from the service signaling that it has finished loading in the following manner: constructor(public contentService: ContractServic ...

Steps for configuring mode as 'open' when generating a shadow element with vue-custom-element

Here is the method I used to generate a shadow component Vue.customElement('my-element', MyElement, { shadow: true, shadowCss: mystyles, }); ...

The value of data in Vue.js remains stagnant even after reassignment

In my data setup, I have defined the following: data() { return { mdrender: '', markdown: '' }; }, Additionally, I am working with this function: methods: { interpretVars: function(markdown) { $.ge ...

Using Vue2: It is best practice to refrain from directly mutating a prop as the value will be replaced every

I am a beginner in Vue and I am working on improving my skills. Currently, I am facing an issue when using props within a v-for. Here is an example: Template: <template> <div class="row"> <div v-for="question in ques ...

Navigating through a large set of data in a web application can be challenging, but with the async await function

I have been working on an app that utilizes the GitHub API to display a user's repositories from Github. However, I am facing a challenge in fetching data from all pages as I can currently only retrieve repositories from one page. I attempted to addre ...

Show an array of arrays using a visual table representation

I am working with an Array of arrays in my data, and they are structured like this : Now, I am trying to showcase this array in a table, but all I am getting is a blank page. Here is the HTML code for the table (I have included only the first column' ...

An unconventional approach to utilizing Vue CLI for personal projects

Currently, I have built a Vue application with Bootstrap-Vue, Express (Node.js), and MySQL. The project is being developed using vue-cli and is in development mode. The client and server are separated into different folders to create a single-page applicat ...

Exploring Angular 10 Formly: How to Retrieve a Field's Value within a Personalized Formly Wrapper

Utilizing Angular 10, I have a formly-form with a select-field named session. This select field provides options from which to choose a dndSession. Each option holds key-value pairs within an object. I want to add a button next to the select-field that tr ...