"Mastering the Composition API in Vue 3: A guide to defining props within the setup() method

I created a custom "loading state" mixin specifically for Vue 2:

export default {
  props: {
    loading: {
      type: Boolean,
      default: false
    },
  },
  data () {
    return {
      innerLoading: false,
    }
  },
  mounted () {
    this.innerLoading = !!this.loading
  },
  methods: {
    startLoading () {
      this.$emit('update:loading', this.innerLoading = true)
    },
    stopLoading () {
      this.$emit('update:loading', this.innerLoading = false)
    },
  },
  computed: {
    isLoading () {
      return !!this.innerLoading
    },
    isNotLoading () {
      return !this.innerLoading
    },
  },
  watch: {
    loading (loading) {
      this.innerLoading = !!loading
    },
  }
}

This mixin is used in various components to manage the loading state such as forms, buttons, and tables.

Now, I am looking to refactor this mixin into the composition API style for Vue 3. My goal is to utilize the loading composable like this:

// components/Table.vue

import 'useLoading' from 'src/composables/loading'

export default defineComponent({
  setup () {
    const { startLoading, stopLoading, innerLoading } = useLoading()

    // ...
    
    return { startLoading, stopLoading, innerLoading, ... }
  }
})

My issue:

// How can I declare the loading prop within the setup() function?
props: {
  loading: {
    type: Boolean,
    default: false
  },
},

One approach is to define my component like this:

import 'useLoading' from 'src/composables/loading'

export default defineComponent({
  props: {
    loading: {
      type: Boolean,
      default: false
    },
  },
  setup () {
    const { startLoading, stopLoading, innerLoading } = useLoading();
  }
})

However, if I have multiple components using this mixin/composable, it would be more efficient to declare the loading prop only ONCE (similar to how it was done in the mixin).

Is there a way to achieve this with the composition API?

Answer №1

One possible approach could involve implementing the following code snippet:

import {withProps, useLoading} from "src/composables/loading";

export default defineComponent({
  props: {
    ...withProps()
  },
  setup () {
    const { startLoading, stopLoading, innerLoading } = useLoading();
  }
})

In this example, withProps functions as a container for your definitions.

export const withProps = () => ({
  loading: {
    type: Boolean,
    default: false
  },
})

While it is not mandatory for withProps to be defined as a function, there are instances where preemptively structuring it in this manner can help maintain consistency in the API design.

Answer №2

Create an Object named loadingProps in a separate file called makeLoadingProps:

export const loadingProps = {
    loading: {
        type: Boolean,
        default: false
    }
}

Next, include it in your component using the script setup syntax:

<script setup lang="ts">

import {defineProps} from 'vue'
import { loadingProps } from 'src/composables/makeLoadingProps';

const props = defineProps({
               ...loadingProps,
                //other props
             })

const { startLoading, stopLoading, innerLoading } = useLoading(props)

</script>

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

Potential delay in mounting Rails Webpacker + Vue components when webpack-dev-server is not utilized

Production Delay in Rendering Process While using webpack-dev-server, all components are rendered quickly and function flawlessly. However, when running the application solely through rails s in both development and production, I can witness a noticeable ...

Exploring the Power of Ajax Interceptor in Framework7-vue-cli

I have a challenge where I need to redirect all ajax requests with a status code of -1 in the response to the login screen. Despite my efforts, I am unable to monitor it. What steps should I take next? Appreciate your help. My approach: app.js Framework7. ...

Is there a way to access a component based on the parameter in the Vue router?

I am working on a Vue component called Portfolio.vue, which contains a child component called Category.vue. I am able to navigate to the Category.vue component using <router-link :to = "{ name: 'category', params: { id: id }}"> wh ...

I'm encountering a problem with my vuejs application

I am currently working on a new vuejs 2 app and encountered an unexpected error. ERROR in ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!./src/components/Customers.vue Module build failed: S ...

Guide to creating a versatile bootstrap modal window in Vue.js

I need some assistance with creating a bootstrap modal window that provides a warning to the user before they take an action. The issue I am facing is that when I enter text into a field, close the modal, and then reopen it, the previous values are still t ...

Switching the default port for a Vue.js application running in a Docker container

I am currently in the process of changing the default port for a Vue.js app running on docker. I have experimented with both examples provided in the official documentation, which can be found here. For instance, I have a Dockerfile using http-server: FR ...

Exploring Vue.js: The Power of Components and Cache

After researching ways to 'cache' API fetched data in my application, I discovered that it can be easily achieved using localStorage or sessionStorage. Although it functions well, I am interested in consolidating all cached data into a single JS ...

Why am I unable to utilize methods in Vue.js?

Hey everyone, I'm currently working on a website that includes a home page and a specific 'Brazil' component. To switch between the two, I am using vue router. Within the Brazil component, there is a calculator feature that should take a gra ...

Retrieving a single document using Firebase with VueJS

My goal is to retrieve a specific document from firebase using the auto-generated ID as my route parameter. However, I am not getting any data in return. I want to use the when() method to fetch a document with an auto-generated ID that matches my query, ...

Transforming the Blade user profile into a sleek Vue interface for the Laravel-Vue project

They have requested me to convert all pages from blade to vuejs. I have begun the process with the user profile (Profile.vue), but I am unsure about how to execute PUT requests using Axios in this case. Can someone provide guidance on creating the code for ...

Issue encountered when sending a Laravel route as a prop in VueJS

When trying to implement the blade syntax route() in a vue js component, I attempted the following code: <nav-bar :user="{{ json_encode(Auth::user()) }}" :authPath= "{{ route('auth') }}"> </nav-bar> An error popped up in the cons ...

Troubleshooting missing images in Vue.js/Laravel application when using Laravel storage directory

Having trouble displaying images dynamically from the Laravel storage folder. Despite seeing the pictures adding up in the folder, it keeps saying images not found. I've even tried using `php artisan link` but no luck. <v-btn flat v-on="on&quo ...

The Vue directive v-for with an empty key attribute does not function properly

Looking for some assistance. In my App.vue file, I have the following code: <template> ... <select class="form-control"> <option v-for="{car, index} in cars" :key="index"> {{ car.name }} </option> </select> ...

Extracting an ID value from a select box in Vue.js

I'm attempting to extract the value of idTipoExame from the following JSON: { "idTipoExame": "11", "mnemonico": "AUR", "exame": "ACIDO URICO" }, { "idTipoExame": "24&qu ...

How to utilize a PHP array within a Vue.js template

I have been exploring the realms of Laravel and vue.js recently and have encountered a challenge. Within my Laravel model, I have a PHP method that retrieves data from a database and organizes it into objects stored in an array. Now, my goal is to access t ...

Managing Uploaded Files using Laravel and Vue.js

Currently, I am in the process of developing a Vue.js + Vuetify + Axios + Laravel framework for creating a dashboard. One of the functionalities I am working on is the user profile, which includes the ability for users to upload a profile picture and their ...

Vue is removing a DOM node during the created lifecycle hook to set up a component

I am currently working on understanding the issue with this example that is not behaving as expected. My goal is to initialize my ContentView using the server-side rendered HTML in the DOM. I plan to check if init__main-content exists and then initialize t ...

Customizing Axios actions in Vue JS using a variable

I have a form in my Vue component that sends a reservation object to my API for storage. I am exploring the possibility of setting the axios action dynamically based on a variable's value, without duplicating the entire axios function (as both the pos ...

Error: Vuex commit fails due to JSON circular structure issue

Using Vue.js along with the vuex store, I make an API call to validate an item, which returns arrays of errors and warnings. Below is my vuex action : export function validateitemReview ({ commit, dispatch, state }, { reviewId, type, itemreviewData }) { ...

Troubleshooting: Unable to use setOption method in Vue-Dropzone

I am attempting to dynamically set the URL on a dropzone element's options. The documentation specifies that you should use the setOption method to change options after initialization. Here is what I have tried: var url = 'http://myurl' th ...