jeecgboot/JeecgBoot · error

useDrawer() can only be used inside setup() or functional co

Error message

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

What it means

useDrawer is the controller-side hook for the Drawer component pair (useDrawer/useDrawerInner). It creates a ref to hold the drawer instance and registers tryOnUnmounted cleanup for the data-transfer map and visible-state tracking. Because the cleanup and the uid ref rely on an active component instance, the hook guards with getCurrentInstance() and throws if invoked outside a setup context. This mirrors the pattern used by useModal and useDescription.

Source

Thrown at jeecgboot-vue3/src/components/Drawer/src/useDrawer.ts:18

import type { UseDrawerReturnType, DrawerInstance, ReturnMethods, DrawerProps, UseDrawerInnerReturnType } from './typing';
import { ref, getCurrentInstance, unref, reactive, watchEffect, nextTick, toRaw, computed } from 'vue';
import { isProdMode } from '/@/utils/env';
import { isFunction } from '/@/utils/is';
import { tryOnUnmounted } from '@vueuse/core';
import { isEqual } from 'lodash-es';
import { error } from '/@/utils/log';

const dataTransferRef = reactive<any>({});

const visibleData = reactive<{ [key: number]: boolean }>({});

/**
 * @description: Applicable to separate drawer and call outside
 */
export function useDrawer(): UseDrawerReturnType {
  if (!getCurrentInstance()) {
    throw new Error('useDrawer() can only be used inside setup() or functional components!');
  }
  const drawer = ref<DrawerInstance | null>(null);
  const loaded = ref<Nullable<boolean>>(false);
  const uid = ref<string>('');

  function register(drawerInstance: DrawerInstance, uuid: string) {
    isProdMode() &&
      tryOnUnmounted(() => {
        drawer.value = null;
        loaded.value = null;
        dataTransferRef[unref(uid)] = null;
      });

    if (unref(loaded) && isProdMode() && drawerInstance === unref(drawer)) {
      return;
    }
    uid.value = uuid;
    drawer.value = drawerInstance;

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Call useDrawer() synchronously at the top of <script setup> or setup().
  2. If you need to control the drawer from outside setup, keep the hook call in setup and expose/return the methods to wherever they are needed.
  3. Ensure the component using useDrawer is actually rendered within a Vue component tree (not a standalone function).
  4. For shared cross-component drawer control, use a Pinia store that holds the methods reference rather than calling the hook repeatedly.

Example fix

// before — hook called in a store action
actions: {
  openDrawer() {
    const [register, methods] = useDrawer(); // throws
  }
}

// after — call in component setup, delegate to store
// MyPage.vue
const [register, methods] = useDrawer();
drawerStore.setMethods(methods);
Defensive patterns

Strategy: validation

Validate before calling

import { getCurrentInstance } from 'vue';
function safeUseDrawer() {
  if (!getCurrentInstance()) {
    throw new Error('useDrawer must be called in setup(); move the call into <script setup>');
  }
  return useDrawer();
}

Type guard

import { getCurrentInstance } from 'vue';
const isInsideComponent = () => getCurrentInstance() !== null;

Try / catch

try {
  const [register, methods] = useDrawer();
} catch (e) {
  // recover by deferring drawer control to a store set in setup
}

Prevention

When it happens

Trigger: Calling useDrawer() inside a non-setup function, a Pinia store, a utility module, a router guard, or any async continuation that has lost the component instance. Also triggered when the hook is imported and invoked in a plain .ts file rather than a .vue component.

Common situations: Moving drawer-control logic into a shared composable or store; calling openDrawer from a global event bus handler; refactoring that splits the register call from setup; testing the hook in isolation without a Vue instance.

Related errors


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