DEV Community

loading...
Cover image for A quick tip!!!

A quick tip!!!

kaloyanyosifov profile image Kaloqn ・2 min read

Hello everybody 👋

I am reallllllllly tired of writing the same code on every component when making a request. I want to make things simple and my guess is that you want too. Check out my examples to see my tips on such things 😃.

Currently, when we want to get something from an API, we write the code below ... at least I did 😃

<template>
  <div class="section-orders">
    <ul v-if="!loading && orders.length" class="orders">
      <li v-for="order in orders" :key="order.id">{{ order.name }}</li>
    </ul>

    <span v-if="loading">Loading...</span>

    <span v-if="errorMessage">{{ errorMessage }}</span>
  </div>
</template>

<script>
/**
 * External dependencies.
 */
import axios from 'axios';
import { ref } from '@vue/composition-api';

export default {
  name: 'OrdersSection',

  setup() {
    const errorMessage = ref('');
    const loading = ref(false);
    const orders = ref([]);
    const fetchOrders = async () => {
      if (loading.value) {
        return;
      }

      errorMessage.value = '';

      try {
        loading.value = true;
        const response = await axios.get('/orders');
        orders.value = response.data;
      } catch (error) {
        errorMessage.value = 'An error has ocurred!';
      } finally {
        loading.value = false;
      }
    };
    fetchOrders();

    return {
      orders,
      loading,
      errorMessage,
    };
  },
};
</script>

Enter fullscreen mode Exit fullscreen mode

This is ok if we are only going to use it on one component. But if we want to retrieve the orders in a different component, we can either copy the code above or create a composition function to extract the logic for it.

It can look something like this.

<template>
  <div class="section-orders">
    <ul v-if="!loading && orders.length" class="orders">
      <li v-for="order in orders" :key="order.id">{{ order.name }}</li>
    </ul>

    <span v-if="loading">Loading...</span>

    <span v-if="errorMessage">{{ errorMessage }}</span>
  </div>
</template>

<script>
/**
 * Internal dependencies.
 */
import useOrders from '@/components/bank-form/use-orders';

export default {
  name: 'OrdersSection',

  setup() {
    const { loading, errorMessage, orders } = useOrders();

    return {
      orders,
      loading,
      errorMessage,
    };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

and the useOrders composition function:

/**
 * External dependencies.
 */
import axios from 'axios';
import { ref } from '@vue/composition-api';

export default function useOrders() {
    const errorMessage = ref('');
    const loading = ref(false);
    const orders = ref([]);
    const fetchOrders = async () => {
        if (loading.value) {
            return;
        }

        errorMessage.value = '';

        try {
            loading.value = true;
            const response = await axios.get('/orders');
            orders.value = response.data;
        } catch (error) {
            errorMessage.value = 'An error has ocurred!';
        } finally {
            loading.value = false;
        }
    };
    fetchOrders();

    return {
        orders,
        loading,
        errorMessage,
    };
}
Enter fullscreen mode Exit fullscreen mode

Great!!!!!
GREAT


But after some time you need to do the same logic for another request and it becomes tedious to write the same, "loading, errorMessage and data" state.

This is so much easy with @cytools/vue-query.

Here is an example


<template>
  <div class="section-orders">
    <ul v-if="!isLoading && orders.length" class="orders">
      <li v-for="order in orders" :key="order.id">{{ order.name }}</li>
    </ul>

    <span v-if="isLoading">Loading...</span>

    <span v-if="error">{{ error }}</span>
  </div>
</template>

<script>
/**
 * Internal dependencies.
 */
import axios from 'axios';
import { useQuery } from '@cytools/vue-query';

export default {
  name: 'OrdersSection',

  setup() {
    const { isLoading, error, data: orders } = useQuery(
        'orders',
        async () => {
          return (await axios.get('/orders')).data;
        },
        {
          defaultData: [],
        },
    );

    return {
      orders,
      isLoading,
      error,
    };
  },
};
</script>

Enter fullscreen mode Exit fullscreen mode

boom

We've done everything with less code and get free caching of the data based on the key.

Here is a link to the library for more details -- https://github.com/cytools/vue-query

There is a lot more fun than just the example above.

Discussion (0)

Forem Open with the Forem app