vue3 composition api로 재사용가능한 코드 만들기 & toRefs 기능

vue3의 composition api를 사용하면 로직을 재사용할 수 있습니다.

직접 짜보니 react hook과 흡사하다는 생각이 많이 들었습니다.

supabase에서 id에 해당하는 data의 한글이름을 가져오는 코드를 재사용하기 위해 짜보았습니다.

// @/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 }
}

여기서 눈여겨볼 점은 state를 ...toRefs(state)의 형태로 반환하는 점입니다. 이렇게 해야 반응성이 유지된다고 하는데요. 이 모듈을 컴포넌트에서 불러와서 사용해봤습니다.

const { userKoreanName, loadUserKoreanName } = useKoreanName();

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

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

template에서 userKoreanName을 출력하는데 아래와 같이 잘 동작하는 것을 볼 수 있습니다.

image

만약에 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 }
}

이 경우에는 로그를 찍어보면 useUserKoreanName 함수 내부에서는 state가 반응성을 띕니다.

image

하지만 컴포넌트에서 userKoreanName을 출력해보면 기본값이 들어가 있는 것을 확인할 수 있습니다.

image

toRefs에 관한 공식문서 공식문서를 살펴보면 toRefs는 composable function에서 반응형의 객체를 반환할 때, 사용하는 컴포넌트에서는 객체를 destructure나 spread를 하더라도 반응성을 잃지 않도록 한다고 합니다.


Written by@Donghoon Song
사람들의 꿈을 이어주는 코멘토에서 일하고 있습니다.

InstagramGitHubTwitterLinkedIn