Skip to content

[bug]: Slider Component Fails to Handle Single Numeric value Props and Breaks Controlled State #10890

@lt7

Description

@lt7

Describe the bug

The Shadcn Slider component does not correctly parse single numeric values for the value or defaultValue props. It incorrectly falls back to a dual-thumb state [min, max] when it should render a single-thumb state [value].

Furthermore, because of an unstable dependency check in React.useMemo, wrapping the value in an array (e.g., value={[field.value]}) causes infinite re-renders during drag interactions, making the component unusable in controlled forms (like react-hook-form).

🔍 Technical Root Cause
The bug resides in https://github.com/shadcn-ui/ui/blob/main/apps/v4/registry/bases/base/ui/slider.tsx#L13 within the calculation of the internal _values array:

// Current Buggy Implementation

const _values = React.useMemo(
  () =>
    Array.isArray(value)
      ? value
      : Array.isArray(defaultValue)
        ? defaultValue
        : [min, max],
  [value, defaultValue, min, max],
);

Incorrect Logic: If value is a number (e.g. 0.5), the Array.isArray(value) check fails, and it defaults to [min, max].
Reference Instability: When developers pass [field.value], a new array reference is created on every render. Because value is a dependency of useMemo, the internal _values array is recalculated constantly, causing the primitive to lose its internal transition/drag state.

Proposed Fix: Update the useMemo block to explicitly check for undefined and properly wrap single values in an array:

const _values = React.useMemo(() => {
  if (Array.isArray(value)) return value;
  if (value !== undefined) return [value];
  if (Array.isArray(defaultValue)) return defaultValue;
  if (defaultValue !== undefined) return [defaultValue];
  return [max]; // Default to single thumb
}, [value, defaultValue, max]);

This change allows the component to support the standard API expected by Shadcn users while maintaining stable references for single-thumb sliders.

Affected component/components

Slider

How to reproduce

  1. Use the component in a controlled form.
  2. Pass a single number to the value prop:
  3. Observed Behavior: The slider renders two thumbs (one at 0, one at 100).
  4. Attempt to fix it by passing an array:
    Observed Behavior: The slider "stutters" or remains frozen because the internal useMemo triggers a re-render on every mouse movement, dropping the active drag state of the primitive.

Codesandbox/StackBlitz link

No response

Logs

System Info

Chrome

Before submitting

  • I've made research efforts and searched the documentation
  • I've searched for existing issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions