Vue 3 Get composable variables out of function without redefining refs

Viewed 523

I'm working with a parent companyList component, a reusable Table component and an useFetch composable in vue 3.2

Without the Table component I had the following code:

companyList

<script setup>
    import { computed } from 'vue';
    import useFetch from '@/composables/useFetch';
    import { formatEmail, formatPhone, formatEnterpriseNumber } from '@/utils/formatters';

    const { response, isFetching, error } = useFetch('get', '/companies');

    const companies = computed(() =>
        response.value?.companies?.map((company) => ({
            id: `#${company.id}`,
            name: `${company.legal_entity_type} ${company.business_name}`,
            enterprise_number: formatEnterpriseNumber(company.enterprise_number),
            email: formatEmail(company.email),
            phone: formatPhone(company.phone),
        }))
    );
</script>

In the Table component which contains pagination, sorting and a search, a watchEffect checks if the state has changed and triggers an emit from the parent component. In this case getCompanies. This looks like this:

companyList

<script setup>
    const getCompanies = (search, sortKey, orderKey) => {
        const { response, isFetching, error } = useFetch('get', '/companies', {
            params: {
                keyword: search,
                sort_by: sortKey,
                order_by: orderKey,
            },
        });
    };

    const companies = computed(() =>
        response.value?.companies?.map((company) => ({
            id: `#${company.id}`,
            name: `${company.legal_entity_type} ${company.business_name}`,
            enterprise_number: formatEnterpriseNumber(company.enterprise_number),
            email: formatEmail(company.email),
            phone: formatPhone(company.phone),
        }))
    );
</script>

<template>
    <Spinner v-if="isFetching" size="medium" />
    <ErrorMessage v-else-if="error" showReload :description="error" />
    <NoDataMessage v-else-if="!companies || companies.length <= 0" />
    <div v-else>
        <Table :columns="tableColumns" :data="companies" @fetchData="getCompanies">
            <template v-slot:id="{ item }">
                <Badge>
                    {{ item.id }}
                </Badge>
            </template>
            <template v-slot:actions="{ item }">
                <router-link :to="{ name: 'clientDetails', params: { client_id: item.id } }" class="text-blue-500 lowercase"> {{ $tc('detail', 2) }} </router-link>
            </template>
        </Table>
    </div>
</template>

Question: How can I get the response, isFetching and error out of the getCompanies function and use it inside the template tags? It feels like a waste of using a reusable system if I have to define refs to get them out. On top of that I can't use the same names. Is there another solution than this:

const local_response = ref(null);
const local_isFetching = ref(null);
const local_error = ref(null);

const getCompanies = (search, sortKey, orderKey) => {
    const { response, isFetching, error } = useFetch('get', '/companies', {
        params: {
            keyword: search,
            sort_by: sortKey,
            order_by: orderKey,
        },
    });

    local_response.value = response;
    local_isFetching.value = isFetching;
    local_error.value = error;
};

const companies = computed(() =>
    local_response.value?.companies?.map((company) => ({
        id: `#${company.id}`,
        name: `${company.legal_entity_type} ${company.business_name}`,
        enterprise_number: formatEnterpriseNumber(company.enterprise_number),
        email: formatEmail(company.email),
        phone: formatPhone(company.phone),
    }))
);
1 Answers

useFetch provides an option to delay execution until you want to:

const {  execute: getCompanies, response, isFetching, error } =  useFetch('get', 
 '/companies', {
    immediate: false, // defer execution until execute is called
    params: {
        keyword: search,
        sort_by: sortKey,
        order_by: orderKey,
    },
});

// getCompanies, response, isFetching, and error will all be available to the template 
Related