Skip to content

Add programmatic value control via prop to keep UI in sync with external state #116

@KlementMultiverse

Description

@KlementMultiverse

Problem

Currently, the CircularSlider component initializes with a defaultValue prop but has no way to update its internal state from external React state after mount. This creates a common pattern mismatch: if a parent component needs to reset, update, or sync the slider's value (e.g., via form submission, undo/redo, or multi-step wizard), the UI becomes out of sync with the actual application state.

Example scenario:

const [savedValue, setSavedValue] = useState(0);
const [sliderValue, setSliderValue] = useState(0);

// User changes slider
const handleSliderChange = (value) => setSliderValue(value);

// User clicks "Reset" — no way to programmatically update the slider
const handleReset = () => {
  setSavedValue(0);
  // ❌ No prop to tell CircularSlider to move back to 0
  setSliderValue(0);
};

The component stores state internally (startAngle, currentValue) but provides no value prop to override it—only defaultValue for initialization.

Why This Matters

  1. State management patterns: Modern React apps commonly lift state up for undo/redo, form validation, or cross-component coordination. CircularSlider breaks this pattern.
  2. Accessibility and UX: Users expect "Reset" buttons to work. Without this, sliders feel broken or unresponsive.
  3. Comparison to standard inputs: HTML <input type="range"> accepts both initial and controlled values. CircularSlider should follow this convention.

Proposed Solution

Add a value prop (optional, controlled) alongside the existing defaultValue (uncontrolled). When value is provided and changes, the component should update its internal currentValue and knob position accordingly:

interface CircularSliderProps {
  defaultValue?: number;  // Uncontrolled: used only on mount
  value?: number;         // Controlled: updates UI when prop changes
  onChange?: (value: number) => void;
  // ... existing props
}

Behavior:

  • If only defaultValue is set → uncontrolled mode (current behavior)
  • If value is set → controlled mode, internal state syncs with prop
  • When value changes externally, the knob smoothly moves to the new position

Example Usage

<CircularSlider
  value={externalValue}          // Controlled by parent
  onChange={handleChange}
  defaultValue={0}               // Still used if value is undefined
/>

This mirrors the pattern of <input value={state} onChange={setState} /> and <input defaultValue={initial} /> in React.


Contributed by Klement Gunndu

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions