Frontend Development 23 min read

Using and Building Custom Hooks in Vue 3

This article explains what Hooks are, demonstrates how to use them in Vue 3, and guides readers through building reusable custom Hook functions such as useMouse and useTable, covering pagination, parameter handling, and best practices for clean, maintainable frontend code.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Using and Building Custom Hooks in Vue 3

Vue 3 defines a composable (Hook) as a function that leverages the Composition API to encapsulate and reuse stateful logic, a concept borrowed from React Hooks. The article starts by introducing the definition and the difference between ordinary functions and Hook functions that contain reactive state.

It first shows a plain implementation that tracks mouse coordinates directly in a component, requiring duplicated code and lifecycle hooks ( onMounted , onUnmounted ) for each usage:

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const x = ref(0);
const y = ref(0);
function update(event) { x.value = event.pageX; y.value = event.pageY; }
onMounted(() => window.addEventListener('mousemove', update));
onUnmounted(() => window.removeEventListener('mousemove', update));
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>

Next, the same functionality is refactored into a custom Hook useMouse , dramatically simplifying component code:

<script setup>
import { useMouse } from './mouse.js';
const { x, y } = useMouse();
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>

The tutorial then builds a more practical Hook useTable for fetching table data. An initial version returns an array [data, refresh] and abstracts the API call, reducing repetitive code when multiple tables are present.

import { ref } from 'vue';
export function useTable(api) {
  const data = ref([]);
  const refresh = () => api().then(res => data.value = res);
  refresh();
  return [data, refresh];
}

To handle pagination, sorting, and loading states, the article introduces usePagination and extends useTable to accept options for data paths, immediate execution, and custom parameters. The enhanced Hook returns [data, refresh, loading, pagination] and supports automatic total count handling, loading indicators, and flexible request payload construction.

export function useTable(api, options = {}) {
  const [pagination, , , setTotal] = usePagination(() => refresh());
  const data = ref([]);
  const loading = ref(false);
  const refresh = () => {
    loading.value = true;
    return api({ page: pagination.current, limit: pagination.size })
      .then(res => { data.value = get(res, options.path?.data, []); setTotal(get(res, options.path?.total, 0)); })
      .finally(() => { loading.value = false; });
  };
  options.immediate && refresh();
  return [data, refresh, loading, pagination];
}

Advanced parameter strategies are discussed, including passing static objects, reactive objects, or functions that return parameter objects, allowing the Hook to adapt to changing query criteria such as user‑selected IDs. The final version also lets the refresh function accept extra parameters at call time, making the Hook suitable for complex UI interactions.

const refresh = (extraData) => {
  const request = { page: pagination.current, size: pagination.size, ...(extraData || {}), ...(typeof params === 'function' ? params() : params) };
  loading.value = true;
  return api(request).then(res => { data.value = get(res, options.path?.data, []); setTotal(get(res, options.path?.total, 0)); })
    .finally(() => { loading.value = false; });
};

In conclusion, the article demonstrates how Hooks enable stateful logic reuse in Vue, improve code readability, and, when combined with component encapsulation, lead to highly maintainable frontend applications.

frontendJavaScriptVueHooksComposition API
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.