Data Provider component in Vue.js

By using component-based technologies such as Vue.js, doesn't mean that all components must be UI based.

In fact, my favourite way to apply advanced reusability in large applications is by using component composition.

With scoped slots, as you haven seen in "Using scoped slots in Vue.js", you can encapsulate logic in another component and pass it to a slot via props. That allows you to compose the UI and behaviour of a new component by combining multiple of them.

Today, I'm going to show you a Data provider Component example.

Data Provider is a renderless component, meaning that it doesn't need to render anything.

The base to create a renderless component is to create a scoped slot from a render function and pass any prop to it:

render() {
  return this.$scopedSlots.default({
    loading: !this.loaded,
    data: this.data
  });
}

Due to an inconsistency on scoped slots (fixed by version 2.6), you can better do it like this to make it work in any case:

render() {
  const slot = this.$scopedSlots.default({
    loading: !this.loaded,
    data: this.data
  });

  return Array.isArray(slot) ? slot[0] : slot;
}

Knowing that, to create a Data Provider component you must perform an ajax/fetch call when the component is created, and then pass that data to the scoped slot.

A final version of DataProvider.js could be:

import axios from "axios";

export default {
  props: ["url"],
  data: () => ({
    data: null,
    loaded: false
  }),
  created() {
    axios.get(this.url).then(({ data }) => {
      this.data = data;
      this.loaded = true;
    });
  },
  render() {
    const slot = this.$scopedSlots.default({
      loading: !this.loaded,
      data: this.data
    });

    return Array.isArray(slot) ? slot[0] : slot;
  }
};

Notice that it's a .js file. Since it just has the script part of the component, it doesn't need to be a .vue file.

The Data Provider component also is holding a loading state, so you can use that to render different UI depending on that state. An example could be:

<template>
  <DataProvider url="https://jsonplaceholder.typicode.com/users">
    <div v-slot="{ data, loading }">
      <div v-if="loading">Loading...</div>
      <div v-else>
        <h2>Result: {{ data.length }} users</h2>
        <p v-for="user in data" :key="user.id">{{ user.name }}</p>
      </div>
    </div>
  </DataProvider>
</template>

That's it!

If you want to check this example running, go to this CodeSandbox!

Don't forget to share VueDose with your colleagues, so they also know about these tips as well!

See you next week.

Alex

Don't miss out anything about Vue, your favourite framework.

Subscribe to receive all the articles we publish in a concise format, perfect for busy devs.

Related Articles

The new Provide and Inject in Vue 3

Getting stuck into the prop drilling? Learn how provide/inject can make your components more flexible and independent in this short tutorial.

Anthony Konstantinidis

Anthony Konstantinidis

Jul 18, 2022

Using Scoped Slots in Vue.js

Quick example on how to use scoped slots for component reusability in vuejs

Alex Jover Morales

Alex Jover Morales

Sep 15, 2019

Create an ImageSelect component on top of vue-multiselect

Build an ImageSelect Vue.js component using the popular vue-multiselect package following the Adaptive Components pattern.

Alex Jover Morales

Alex Jover Morales

Feb 24, 2019

Sponsors

VueDose is proudly supported by its sponsors. If you enjoy it, consider supporting it to ensure the project maintainability.

Silver
Learning Partner