Skip to content

[Bug]: useId check is failing when the project's Vue version is less than 3.5 #2122

@MrSunshyne

Description

@MrSunshyne

Environment

System:
    OS: Linux 5.0 undefined
    CPU: (5) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 20.19.1 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.8.2 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    reka-ui: 2.4.1 => 2.4.1 
    vue: 3.4.27 => 3.4.27

Link to minimal reproduction

https://stackblitz.com/~/github.com/MrSunshyne/reka-ui-useid-reproduction

Steps to reproduce

Describe the bug

Reka-UI useId Bug Reproduction

This is a minimal reproduction case for the useId build issue with reka-ui and Vue 3.4.27.

Reproduction Steps

  1. Navigate to the reproduction directory:

    cd packages/reka-repro
  2. Install dependencies:

    pnpm install
  3. Try to build the project:

    pnpm build
  4. Observe the build error:

    "useId" is not exported by "vue.runtime.esm-bundler.js", imported by "reka-ui/dist/shared/useId.js"
    

If you switch the version of Vue to 3.5.x, then the error disappears during build.

Describe the bug

The Issue

When building a Vue 3.4 application that uses reka-ui components, the build fails with:

export 'useId' (imported as 'vue') was not found in 'vue' (possible exports: BaseTransition, BaseTransitionPropsValidators, Comment, DeprecationTypes, EffectScope, ErrorCodes, ErrorTypeStrings, Fragment, KeepAlive, ReactiveEffect, Static, Suspense, Teleport, Text, TrackOpTypes, Transition, TransitionGroup, TriggerOpTypes, VueElement, assertNumber, callWithAsyncErrorHandling, callWithErrorHandling, camelize, capitalize, cloneVNode, compatUtils, compile, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createHydrationRenderer, createPropsRestProxy, createRenderer, createSSRApp, createSlots, createStaticVNode, createTextVNode, createVNode, customRef, defineAsyncComponent, defineComponent, defineCustomElement, defineEmits, defineExpose, defineModel, defineOptions, defineProps, defineSSRCustomElement, defineSlots, devtools, effect, effectScope, getCurrentInstance, getCurrentScope, getTransitionRawChildren, guardReactiveProps, h, handleError, hasInjectionContext, hydrate, initCustomFormatter, initDirectivesForSSR, inject, isMemoSame, isProxy, isReactive, isReadonly, isRef, isRuntimeOnly, isShallow, isVNode, markRaw, mergeDefaults, mergeModels, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onScopeDispose, onServerPrefetch, onUnmounted, onUpdated, openBlock, popScopeId, provide, proxyRefs, pushScopeId, queuePostFlushCb, reactive, readonly, ref, registerRuntimeCompiler, render, renderList, renderSlot, resolveComponent, resolveDirective, resolveDynamicComponent, resolveFilter, resolveTransitionHooks, setBlockTracking, setDevtoolsHook, setTransitionHooks, shallowReactive, shallowReadonly, shallowRef, ssrContextKey, ssrUtils, stop, toDisplayString, toHandlerKey, toHandlers, toRaw, toRef, toRefs, toValue, transformVNodeArgs, triggerRef, unref, useAttrs, useCssModule, useCssVars, useModel, useSSRContext, useSlots, useTransitionState, vModelCheckbox, vModelDynamic, vModelRadio, vModelSelect, vModelText, vShow, version, warn, watch, watchEffect, watchPostEffect, watchSyncEffect, withAsyncContext, withCtx, withDefaults, withDirectives, withKeys, withMemo, withModifiers, withScopeId)

This happens because:

  1. Vue Version Mismatch: Vue 3.4.27 doesn't export useId (it was added in Vue 3.5)
  2. TypeScript Build Issue: reka-ui uses vue.useId?.() syntax which causes TypeScript/build errors
  3. Optional Chaining Problem: The optional chaining with function calls doesn't work properly in build environments

Root Cause

The issue is in reka-ui/src/shared/useId.ts:

if ('useId' in vue) {
  return `${prefix}-${vue.useId?.()}`  // ❌ This causes build errors
}

Even though there's a runtime check 'useId' in vue, the TypeScript compiler and build tools still try to resolve vue.useId?.() and fail because useId is not in Vue 3.4's type definitions.

Expected behavior

Expected Behavior

The build should succeed because reka-ui has runtime checks for useId availability and should fall back gracefully when it's not available.

Context & Screenshots (if applicable)

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions