jeecgboot/JeecgBoot · error

useDescription() can only be used inside setup() or function

Error message

useDescription() can only be used inside setup() or functional components!

What it means

useDescription is a Vue 3 composition-API hook that pairs a Description component with its controller via a register/callback pattern. Like all such hooks, it requires an active component instance to register lifecycle hooks (onUnmounted). It guards by checking getCurrentInstance() at call time — if null, the hook is being invoked outside of setup() and lifecycle registration would silently fail, so it throws immediately rather than producing a broken ref.

Source

Thrown at jeecgboot-vue3/src/components/Description/src/useDescription.ts:7

import type { DescriptionProps, DescInstance, UseDescReturnType } from './typing';
import { ref, getCurrentInstance, unref, onUnmounted } from 'vue';
import { isProdMode } from '/@/utils/env';

export function useDescription(props?: Partial<DescriptionProps>): UseDescReturnType {
  if (!getCurrentInstance()) {
    throw new Error('useDescription() can only be used inside setup() or functional components!');
  }
  const desc = ref<Nullable<DescInstance>>(null);
  const loaded = ref(false);

  function register(instance: DescInstance) {
    // update-begin--author:liaozhiyang---date:20251223---for:【pull/9125】在抽屉中配置destroy-on-close,再次打开未正确渲染
    isProdMode() &&
      onUnmounted(() => {
        desc.value = null;
        loaded.value = false;
      });
    if (unref(loaded) && isProdMode() && instance === unref(desc)) return;
    // update-end--author:liaozhiyang---date:20251223---for:【pull/9125】在抽屉中配置destroy-on-close,再次打开未正确渲染
    desc.value = instance;
    props && instance.setDescProps(props);
    loaded.value = true;
  }

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Move the useDescription() call to the top level of <script setup> or the setup() function body.
  2. If extracting into a composable, ensure the composable itself is called synchronously from setup and calls useDescription synchronously.
  3. Avoid wrapping the call in async/await at the top level — call it first, then await.
  4. If you genuinely need to trigger actions outside setup, use the returned methods object (openModal-style) rather than calling the hook again.

Example fix

// before — called in an async callback
onMounted(async () => {
  const [register, desc] = useDescription(); // throws
});

// after — call synchronously at setup top level
const [register, desc] = useDescription();
onMounted(async () => { /* use desc */ });
Defensive patterns

Strategy: validation

Validate before calling

// Guard the hook call so misuse fails with a clear message in dev
import { getCurrentInstance } from 'vue';
function safeUseDescription(props?: Partial<DescriptionProps>) {
  if (!getCurrentInstance()) {
    console.warn('useDescription called outside setup — skipping');
    return null;
  }
  return useDescription(props);
}

Type guard

import { getCurrentInstance } from 'vue';
function isInSetup(): boolean {
  return !!getCurrentInstance();
}

Try / catch

// If you must call conditionally
let desc;
try {
  desc = useDescription();
} catch (e) {
  // handle missing setup context gracefully
}

Prevention

When it happens

Trigger: Calling useDescription() at module top-level, inside a plain function (not a Vue setup context), inside an async callback resolved after setup returns, inside a setTimeout/setInterval handler, or inside a Pinia store action. Also triggered by calling it inside <script setup> but in a top-level await continuation that detaches from the instance context.

Common situations: Refactoring that moves the hook call out of setup; extracting logic into a composable that forgets to forward the setup context; calling openDescription inside an event handler defined outside setup; SSR or testing utilities that mount components without a proper instance.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/47dd4dc098de8cca. Report an issue: GitHub.