On gists
                Vue.js - Provide pattern
                    
                        
                    
                    
                    
                    Provider.vue
                        Raw
                        #
                    
                        <!-- https://www.patterns.dev/vue/data-provider -->
<!-- Provider.vue -->
<template>
  <slot :data="data" :loading="loading"></slot>
</template>
<script setup>
  import { ref, reactive } from "vue";
  const API_ENDPOINT_URL = "https://official-joke-api.appspot.com/random_joke";
  const data = reactive({
    setup: null,
    punchline: null,
  });
  const loading = ref(false);
  const fetchJoke = async () => {
    loading.value = true;
    const response = await fetch(API_ENDPOINT_URL);
    const responseData = await response.json();
    data.setup = responseData.setup;
    data.punchline = responseData.punchline;
    loading.value = false;
  };
  fetchJoke();
</script>
<!-- Usage: AnyComponent.vue -->
<template>
  <DataProvider v-slot="{ data, loading }">
    <div class="joke-section">
      <p v-if="loading">Joke is loading...</p>
      <p v-if="!loading">{{ data.setup }}</p>
      <p v-if="!loading">{{ data.punchline }}</p>
    </div>
  </DataProvider>
</template>
<script setup>
  import DataProvider from "./components/DataProvider.vue";
</script>
<!-- Could be realized by Composable -->
<!-- UseJoke.js -->
import { ref, reactive } from "vue";
const API_ENDPOINT_URL = "https://official-joke-api.appspot.com/random_joke";
export function useGetJoke() {
  const data = reactive({
    setup: null,
    punchline: null,
  });
  const loading = ref(false);
  const fetchJoke = async () => {
    loading.value = true;
    const response = await fetch(API_ENDPOINT_URL);
    const responseData = await response.json();
    data.setup = responseData.setup;
    data.punchline = responseData.punchline;
    loading.value = false;
  };
  fetchJoke();
  return { data, loading };
}
<!-- Usage -->
<template>
  <div class="joke-section">
    <p v-if="loading">Joke is loading...</p>
    <p v-if="!loading">{{ data.setup }}</p>
    <p v-if="!loading">{{ data.punchline }}</p>
  </div>
</template>
<script setup>
  import { useGetJoke } from "./composables/useGetJoke";
  const { data, loading } = useGetJoke();
</script>