DEV Community

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

Posted on • Updated 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.

Top comments (0)