跪拜 Guibai
← All articles
Frontend · Vue.js

Vue 3 Hooks Replace Mixins for Cleaner Component Logic Reuse

By 独泪了无痕 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Vue 2 Mixins made shared logic hard to trace and prone to property name clashes. Custom Hooks give teams an explicit, tree-shakeable, TypeScript-friendly pattern for extracting stateful logic, which scales better across large codebases.

Summary

Custom Hooks in Vue 3 are ordinary JavaScript functions, conventionally prefixed with `use`, that bundle reactive state, computed properties, watchers, and lifecycle hooks into reusable units. A `useCounter` Hook, for instance, wraps a `ref`-based count and its increment, decrement, and reset methods, then exposes them for any component to destructure directly in `<script setup>`.

This pattern avoids the naming collisions and opaque data sources that plagued Vue 2 Mixins. Logic is organized by feature rather than by option type, so a single Hook can contain the state, methods, and lifecycle hooks that belong together, keeping components thin and focused on the template.

Best practices stress single-responsibility design, parameterization for configurability, and isolating side effects inside lifecycle hooks rather than in the Hook body. Hooks can also compose and nest, though circular dependencies must be avoided.

Takeaways
Custom Hooks are plain functions that use Composition API primitives (`ref`, `reactive`, `watch`, lifecycle hooks) and return state and methods.
Name Hooks with a `use` prefix (e.g., `useCounter`, `useFetch`) to distinguish them from ordinary utility functions.
Each Hook should handle one concern; mixing unrelated logic into a single Hook hurts readability and reuse.
Side effects like DOM manipulation or network calls belong inside lifecycle hooks (`onMounted`, `onUnmounted`), not in the Hook's main body.
Parameterize Hooks with initial values or configuration objects so the same Hook can serve different components.
Hooks can call other Hooks to build layered functionality, but watch for circular dependencies and infinite recursion.
Destructure the returned properties from a Hook directly in `<script setup>`; they remain reactive and template-ready.
Conclusions

The shift from Mixins to Hooks is not just syntactic — it changes how developers trace data flow. With Mixins, a property's origin was often ambiguous; a Hook's explicit import and return make the dependency graph visible.

Vue 3 Hooks borrow the naming convention and mental model from React but ground them in Vue's own reactivity system, which means refs and reactive objects behave differently than React's useState. Developers moving between frameworks need to internalize `.value` access and automatic dependency tracking in `watchEffect`.

The advice to keep side effects out of the Hook body and inside lifecycle hooks is easy to overlook but critical: a Hook that fires a fetch on invocation rather than on mount can cause duplicate requests during server-side rendering or hot module reloading.

Concepts & terms
Composition API
Vue 3's alternative to the Options API that organizes component logic by feature rather than by option type (data, methods, mounted). It uses functions like `ref`, `reactive`, and `watch` inside a `setup` function or `<script setup>` block.
Custom Hook
A plain JavaScript function, conventionally named with a `use` prefix, that encapsulates reactive state and logic using Vue's Composition API primitives. It returns state and methods for components to destructure and use.
Mixins
Vue 2's mechanism for sharing component logic by merging option objects. Mixins often caused naming collisions and made it difficult to trace which mixin provided a given property or method.
ref vs reactive
`ref` wraps a value (primitive or object) in a reactive reference accessed via `.value`; `reactive` makes an entire object reactive and its properties are accessed directly. `toRef` and `toRefs` bridge the two, preserving reactivity during destructuring.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗