DEV Community

Cover image for Writing reusable code with Vue3 composition api
Donghoon Song
Donghoon Song

Posted on • Edited on • Originally published at donghoon-song.github.io

Writing reusable code with Vue3 composition api

Composition api in Vue3 helps to write reusable logic.

When I wrote it myself, I thought it was similar to a React hook.

I have written codes to reuse the logic that fetch data from supabase and extract "korean_name" property of it.

// @/modules/useKoreanName.js
import { supabase } from '@/utils/supabase'
import { reactive, toRefs } from 'vue'

export default function useUserKoreanName() {
  const state = reactive({
    userKoreanName: '이름',
  })
  const loadUserKoreanName = async id => {
    const koreanName = await fetchUserKoreanName(id)
    if (koreanName) state.userKoreanName = koreanName
  }
  const fetchUserKoreanName = async id => {
    try {
      const { data: users } = await supabase
        .from('users')
        .select('korean_name')
        .eq('id', id)
      if (users) {
        return users[0].korean_name
      }
    } catch (error) {
      console.error(error)
    }
  }
  return { ...toRefs(state), fetchUserKoreanName, loadUserKoreanName }
}
Enter fullscreen mode Exit fullscreen mode

What we should pay attention to is that the code returned state in the form of toRefs(state). I heard that this is how we maintain its responsiveness. I imported this module in another component to use it.

const { userKoreanName, loadUserKoreanName } = useKoreanName();

onMounted(() => {
  fetchNotes();
  loadUserKoreanName(id);
});

...
    <div class="text-4xl mr-4">{{ userKoreanName }}  담벼락</div>

Enter fullscreen mode Exit fullscreen mode

The template prints userKoreanName, and you can see that it works well as shown below. (It is my name in Korean)

image

What if we take out toRefs?

// @/modules/useKoreanName.js
import { supabase } from '@/utils/supabase'
import { reactive } from 'vue'

export default function useUserKoreanName() {
  const state = reactive({
    userKoreanName: '이름',
  })
  const loadUserKoreanName = async id => {
    const koreanName = await fetchUserKoreanName(id)
    if (koreanName) state.userKoreanName = koreanName
    console.info('koreanName after load : ', state.userKoreanName)
  }
  const fetchUserKoreanName = async id => {
    try {
      const { data: users } = await supabase
        .from('users')
        .select('korean_name')
        .eq('id', id)
      if (users) {
        return users[0].korean_name
      }
    } catch (error) {
      console.error(error)
    }
  }
  return { ...state, fetchUserKoreanName, loadUserKoreanName }
}
Enter fullscreen mode Exit fullscreen mode

In this case, if you take a log, the state is reactive inside the useUserKoreanName function.

image

However, if you output userKoreanName from the component, you can see that it contains the default value.

image

Official document about toRefs
According to the official document, when toRefs returns a reactive object in a composite function, the component used does not lose its reactivity even if the object is destructed or spreaded.

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →