Understanding and Using Hooks in Vue 3 Composition API
This article introduces Vue 3 Hooks, explains their relationship to the Composition API, compares them with mixins and class‑based patterns, provides best‑practice guidelines, and offers multiple TypeScript code examples for creating, using, and managing custom hooks to improve code reuse and maintainability.
Hooks have become a popular tool in functional programming frameworks such as React, and with the introduction of Vue 3's Composition API, they are gaining traction among Vue developers for their ability to increase code reuse, clarity, and maintainability.
The article first defines Hooks, noting that they originally referred to specific lifecycle callbacks but now, especially after React 16, denote a set of functions prefixed with use that allow developers to avoid class‑based syntax and manage state, lifecycle, and logic reuse directly within functional components. In Vue 3, Hooks are combined with the reactive system and are called composition functions , serving as a tool‑for‑creating‑tools.
It then compares Hooks with the traditional mixin/class approach, highlighting three main drawbacks of mixins/classes: unclear data sources, namespace conflicts, and hidden cross‑module interactions, which lead to maintenance difficulties in large projects. Hooks address these issues by providing clear, isolated state, avoiding naming collisions, and simplifying logic.
The article outlines the advantages of using Hooks, such as clear data origins, no naming conflicts, and concise logic that lets developers focus on core business functionality while reducing repetitive code.
Several code examples demonstrate how to implement Hooks in Vue 3:
<script setup>
import { ref, onMounted } from 'vue'
// reactive state
const count = ref(0)
function increment() {
count.value++
}
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>It also shows a custom useAutoRequest Hook that automatically manages a loading state for API calls, with TypeScript generics for strong typing:
type TApiFun
> = (...params: TParams) => Promise
type AutoRequestResult
> = [Ref
, TApiFun
]
export default function useAutoRequest
(
fun: TApiFun
,
options?: AutoRequestOptions
): AutoRequestResult
{
const { loading = false, onSuccess, onCatch, message } = options ?? { loading: false }
const requestLoading = ref(loading)
const run: TApiFun
= (...params) => {
requestLoading.value = true
return fun(...params)
.then(async res => { onSuccess && (await onSuccess(res)); message && m.success(message); return res })
.catch(async err => { onCatch && (await onCatch(err)); throw new Error(err) })
.finally(() => { requestLoading.value = false })
}
return [requestLoading, run]
}Further, a simple pagination Hook example ( usePagination ) is provided, illustrating how to expose reactive refs and a reset function for pagination state.
interface UsePaginationResponse {
currentPage: Ref
pageSize: Ref
totalCount: Ref
skipCount: Ref
reset: () => void
}
export function usePagination(defaultPageSize?: number): UsePaginationResponse {
const pageSize = ref(defaultPageSize ?? 20)
const currentPage = ref(1)
const totalCount = ref(0)
const skipCount = computed(() => (currentPage.value - 1) * pageSize.value)
function reset() {
currentPage.value = 1
totalCount.value = 0
}
return { currentPage, pageSize, totalCount, skipCount, reset }
}The article also provides practical guidelines for creating custom Hooks: naming must start with use , keep the Hook pure and single‑purpose, ensure inputs drive outputs, handle errors internally, and leverage TypeScript for type safety. It emphasizes that Hooks are most suitable for reusable, stateful logic that would otherwise require repetitive boilerplate.
Additional recommendations include using plugins like unplugin-auto-import for automatic Vue API imports, adopting strict TypeScript settings, avoiding excessive any usage, and following semantic, well‑structured code practices.
In summary, Hooks in Vue 3 enable efficient logic reuse, improve maintainability, and reduce boilerplate, while TypeScript enhances their reliability and developer experience.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.