Skip to content

feat: Add support for automatic reset after React 19 form actions #8444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

devongovett
Copy link
Member

Fixes #6830

In React 19, when a <form> has an action prop that is a function, React will automatically reset the form after the action completes. This occurs after the commit phase of the render following the action so that the defaultValue can be updated based on the data returned by the server (but before layout effects run).

Unlike the builtin <input> element, most of our components use controlled state internally, even when they appear uncontrolled to the user. Changing the defaultValue prop normally does nothing, but with native inputs resetting the form does use the current defaultValue not the original value when the input first mounted. This PR updates all of our components to follow that behavior as well, by updating the internal state to match the current defaultValue when the form is reset.

This also fixes the validation errors being reset after an action, which occurred because the reset event would fire immediately after the validation errors returned by the server were set. Unfortunately react does not give us a way to detect this case, so this implements a best effort: if form.reset() is called programmatically outside a user event, we ignore it and do not clear the validation errors.

import {useLayoutEffect} from './useLayoutEffect';

// Use the earliest effect type possible. useInsertionEffect runs during the mutation phase,
// before all layout effects, but is available only in React 18 and later.
const useEarlyEffect = React['useInsertionEffect'] ?? useLayoutEffect;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that we get the updated defaultValue in the onReset handler of useFormReset, which is called before layout effects run. This is only available in React 18 and later, so we fall back to useLayoutEffect. Shouldn't be a problem because the automatic form reset is React 19 only anyway.

@rspbot
Copy link

rspbot commented Jun 25, 2025

@rspbot
Copy link

rspbot commented Jun 25, 2025

## API Changes

react-aria-components

/react-aria-components:CheckboxGroupState

 CheckboxGroupState {
   addValue: (string) => void
   commitValidation: () => void
+  defaultValue: readonly Array<string>
   displayValidation: ValidationResult
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   isSelected: (string) => boolean
   realtimeValidation: ValidationResult
   removeValue: (string) => void
   resetValidation: () => void
   setInvalid: (string, ValidationResult) => void
   setValue: (Array<string>) => void
   toggleValue: (string) => void
   updateValidation: (ValidationResult) => void
   value: readonly Array<string>
 }

/react-aria-components:ColorAreaState

 ColorAreaState {
   channels: {
     xChannel: ColorChannel
   yChannel: ColorChannel
   zChannel: ColorChannel
 }
   decrementX: (number) => void
   decrementY: (number) => void
+  defaultValue: Color
   getDisplayColor: () => Color
   getThumbPosition: () => {
     x: number
   y: number
   incrementX: (number) => void
   incrementY: (number) => void
   isDragging: boolean
   setColorFromPoint: (number, number) => void
   setDragging: (boolean) => void
   setValue: (string | Color) => void
   setXValue: (number) => void
   setYValue: (number) => void
   value: Color
   xChannelPageStep: number
   xChannelStep: number
   xValue: number
   yChannelPageStep: number
   yChannelStep: number
   yValue: number
 }

/react-aria-components:ColorFieldState

 ColorFieldState {
   colorValue: Color | null
   commit: () => void
   commitValidation: () => void
   decrement: () => void
   decrementToMin: () => void
+  defaultColorValue: Color | null
   displayValidation: ValidationResult
   increment: () => void
   incrementToMax: () => void
   inputValue: string
   realtimeValidation: ValidationResult
   resetValidation: () => void
+  setColorValue: (Color | null) => void
   setInputValue: (string) => void
   updateValidation: (ValidationResult) => void
   validate: (string) => boolean
 }

/react-aria-components:ColorSliderState

 ColorSliderState {
   decrementThumb: (number, number) => void
+  defaultValues: Array<number>
   focusedThumb: number | undefined
   getDisplayColor: () => Color
   getFormattedValue: (number) => string
   getPercentValue: (number) => number
   getThumbMinValue: (number) => number
   getThumbPercent: (number) => number
   getThumbValue: (number) => number
   getThumbValueLabel: (number) => string
   getValuePercent: (number) => number
   incrementThumb: (number, number) => void
   isDisabled: boolean
   isDragging: boolean
   isThumbDragging: (number) => boolean
   isThumbEditable: (number) => boolean
   orientation: Orientation
   pageSize: number
   setFocusedThumb: (number | undefined) => void
   setThumbDragging: (number, boolean) => void
   setThumbEditable: (number, boolean) => void
   setThumbPercent: (number, number) => void
   setThumbValue: (number, number) => void
   setValue: (string | Color) => void
   step: number
   value: Color
   values: Array<number>
 }

/react-aria-components:ColorWheelState

 ColorWheelState {
   decrement: (number) => void
+  defaultValue: Color
   getDisplayColor: () => Color
   getThumbPosition: (number) => {
     x: number
   y: number
   hue: number
   increment: (number) => void
   isDisabled: boolean
   isDragging: boolean
   pageStep: number
   setDragging: (boolean) => void
   setHue: (number) => void
   setHueFromPoint: (number, number, number) => void
   setValue: (string | Color) => void
   step: number
   value: Color
 }

/react-aria-components:ComboBoxState

 ComboBoxState <T> {
   close: () => void
   collection: Collection<Node<T>>
   commit: () => void
   commitValidation: () => void
+  defaultInputValue: string
+  defaultSelectedKey: Key | null
   disabledKeys: Set<Key>
   displayValidation: ValidationResult
   focusStrategy: FocusStrategy | null
   inputValue: string
   isOpen: boolean
   open: (FocusStrategy | null, MenuTriggerAction) => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   revert: () => void
   selectedItem: Node<T> | null
   selectedKey: Key | null
   selectionManager: SelectionManager
   setFocused: (boolean) => void
   setInputValue: (string) => void
   setOpen: (boolean) => void
   setSelectedKey: (Key | null) => void
   toggle: (FocusStrategy | null, MenuTriggerAction) => void
   updateValidation: (ValidationResult) => void
 }

/react-aria-components:DateFieldState

 DateFieldState {
   calendar: Calendar
   clearSegment: (SegmentType) => void
   commitValidation: () => void
   confirmPlaceholder: () => void
   dateFormatter: DateFormatter
   dateValue: Date
   decrement: (SegmentType) => void
   decrementPage: (SegmentType) => void
+  defaultValue: DateValue | null
   displayValidation: ValidationResult
   formatValue: (FieldOptions) => string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   incrementPage: (SegmentType) => void
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   isRequired: boolean
   maxGranularity: 'year' | 'month' | Granularity
   realtimeValidation: ValidationResult
   resetValidation: () => void
   segments: Array<DateSegment>
   setSegment: (SegmentType, number) => void
   setValue: (DateValue | null) => void
   updateValidation: (ValidationResult) => void
   value: DateValue | null
 }

/react-aria-components:DatePickerState

 DatePickerState {
   close: () => void
   commitValidation: () => void
   dateValue: DateValue | null
+  defaultValue: DateValue | null
   displayValidation: ValidationResult
   formatValue: (string, FieldOptions) => string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   isInvalid: boolean
   isOpen: boolean
   open: () => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   setDateValue: (DateValue) => void
   setOpen: (boolean) => void
   setTimeValue: (TimeValue) => void
   setValue: (DateValue | null) => void
   timeValue: TimeValue | null
   toggle: () => void
   updateValidation: (ValidationResult) => void
   value: DateValue | null
 }

/react-aria-components:DateRangePickerState

 DateRangePickerState {
   close: () => void
   commitValidation: () => void
   dateRange: RangeValue<DateValue | null> | null
+  defaultValue: DateRange | null
   displayValidation: ValidationResult
   formatValue: (string, FieldOptions) => {
     start: string
   end: string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   hasTime: boolean
   isInvalid: boolean
   isOpen: boolean
   open: () => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   setDate: ('start' | 'end', DateValue | null) => void
   setDateRange: (DateRange) => void
   setDateTime: ('start' | 'end', DateValue | null) => void
   setOpen: (boolean) => void
   setTime: ('start' | 'end', TimeValue | null) => void
   setTimeRange: (TimeRange) => void
   setValue: (DateRange | null) => void
   timeRange: RangeValue<TimeValue | null> | null
   toggle: () => void
   updateValidation: (ValidationResult) => void
   value: RangeValue<DateValue | null>
 }

/react-aria-components:NumberFieldState

 NumberFieldState {
   canDecrement: boolean
   canIncrement: boolean
   commit: () => void
   commitValidation: () => void
   decrement: () => void
   decrementToMin: () => void
+  defaultNumberValue: number
   displayValidation: ValidationResult
   increment: () => void
   incrementToMax: () => void
   inputValue: string
   minValue?: number
   numberValue: number
   realtimeValidation: ValidationResult
   resetValidation: () => void
   setInputValue: (string) => void
   setNumberValue: (number) => void
   updateValidation: (ValidationResult) => void
   validate: (string) => boolean
 }

/react-aria-components:RadioGroupState

 RadioGroupState {
   commitValidation: () => void
+  defaultSelectedValue: string | null
   displayValidation: ValidationResult
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   lastFocusedValue: string | null
   realtimeValidation: ValidationResult
   resetValidation: () => void
   selectedValue: string | null
   setLastFocusedValue: (string | null) => void
   setSelectedValue: (string | null) => void
   updateValidation: (ValidationResult) => void
 }

/react-aria-components:SelectState

 SelectState <T> {
   close: () => void
   collection: Collection<Node<T>>
   commitValidation: () => void
+  defaultSelectedKey: Key | null
   disabledKeys: Set<Key>
   displayValidation: ValidationResult
   focusStrategy: FocusStrategy | null
   isFocused: boolean
   open: (FocusStrategy | null) => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   selectedItem: Node<T> | null
   selectedKey: Key | null
   selectionManager: SelectionManager
   setFocused: (boolean) => void
   setOpen: (boolean) => void
   setSelectedKey: (Key | null) => void
   toggle: (FocusStrategy | null) => void
   updateValidation: (ValidationResult) => void
 }

/react-aria-components:SliderState

 SliderState {
   decrementThumb: (number, number) => void
+  defaultValues: Array<number>
   focusedThumb: number | undefined
   getFormattedValue: (number) => string
   getPercentValue: (number) => number
   getThumbMaxValue: (number) => number
   getThumbPercent: (number) => number
   getThumbValue: (number) => number
   getThumbValueLabel: (number) => string
   getValuePercent: (number) => number
   incrementThumb: (number, number) => void
   isDisabled: boolean
   isThumbDragging: (number) => boolean
   isThumbEditable: (number) => boolean
   orientation: Orientation
   pageSize: number
   setFocusedThumb: (number | undefined) => void
   setThumbDragging: (number, boolean) => void
   setThumbEditable: (number, boolean) => void
   setThumbPercent: (number, number) => void
   setThumbValue: (number, number) => void
   step: number
   values: Array<number>
 }

/react-aria-components:TimeFieldState

 TimeFieldState {
   calendar: Calendar
   clearSegment: (SegmentType) => void
   commitValidation: () => void
   confirmPlaceholder: () => void
   dateFormatter: DateFormatter
   dateValue: Date
   decrement: (SegmentType) => void
   decrementPage: (SegmentType) => void
+  defaultValue: DateValue | null
   displayValidation: ValidationResult
   formatValue: (FieldOptions) => string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   incrementPage: (SegmentType) => void
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   isRequired: boolean
   maxGranularity: 'year' | 'month' | Granularity
   realtimeValidation: ValidationResult
   resetValidation: () => void
   segments: Array<DateSegment>
   setSegment: (SegmentType, number) => void
   setValue: (DateValue | null) => void
   timeValue: Time
   updateValidation: (ValidationResult) => void
   value: DateValue | null
 }

/react-aria-components:ToggleState

 ToggleState {
+  defaultSelected: boolean
   isSelected: boolean
   setSelected: (boolean) => void
   toggle: () => void
 }

@react-stately/checkbox

/@react-stately/checkbox:CheckboxGroupState

 CheckboxGroupState {
   addValue: (string) => void
   commitValidation: () => void
+  defaultValue: readonly Array<string>
   displayValidation: ValidationResult
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   isSelected: (string) => boolean
   realtimeValidation: ValidationResult
   removeValue: (string) => void
   resetValidation: () => void
   setInvalid: (string, ValidationResult) => void
   setValue: (Array<string>) => void
   toggleValue: (string) => void
   updateValidation: (ValidationResult) => void
   value: readonly Array<string>
 }

@react-stately/color

/@react-stately/color:ColorAreaState

 ColorAreaState {
   channels: {
     xChannel: ColorChannel
   yChannel: ColorChannel
   zChannel: ColorChannel
 }
   decrementX: (number) => void
   decrementY: (number) => void
+  defaultValue: Color
   getDisplayColor: () => Color
   getThumbPosition: () => {
     x: number
   y: number
   incrementX: (number) => void
   incrementY: (number) => void
   isDragging: boolean
   setColorFromPoint: (number, number) => void
   setDragging: (boolean) => void
   setValue: (string | Color) => void
   setXValue: (number) => void
   setYValue: (number) => void
   value: Color
   xChannelPageStep: number
   xChannelStep: number
   xValue: number
   yChannelPageStep: number
   yChannelStep: number
   yValue: number
 }

/@react-stately/color:ColorSliderState

 ColorSliderState {
   decrementThumb: (number, number) => void
+  defaultValues: Array<number>
   focusedThumb: number | undefined
   getDisplayColor: () => Color
   getFormattedValue: (number) => string
   getPercentValue: (number) => number
   getThumbMinValue: (number) => number
   getThumbPercent: (number) => number
   getThumbValue: (number) => number
   getThumbValueLabel: (number) => string
   getValuePercent: (number) => number
   incrementThumb: (number, number) => void
   isDisabled: boolean
   isDragging: boolean
   isThumbDragging: (number) => boolean
   isThumbEditable: (number) => boolean
   orientation: Orientation
   pageSize: number
   setFocusedThumb: (number | undefined) => void
   setThumbDragging: (number, boolean) => void
   setThumbEditable: (number, boolean) => void
   setThumbPercent: (number, number) => void
   setThumbValue: (number, number) => void
   setValue: (string | Color) => void
   step: number
   value: Color
   values: Array<number>
 }

/@react-stately/color:ColorWheelState

 ColorWheelState {
   decrement: (number) => void
+  defaultValue: Color
   getDisplayColor: () => Color
   getThumbPosition: (number) => {
     x: number
   y: number
   hue: number
   increment: (number) => void
   isDisabled: boolean
   isDragging: boolean
   pageStep: number
   setDragging: (boolean) => void
   setHue: (number) => void
   setHueFromPoint: (number, number, number) => void
   setValue: (string | Color) => void
   step: number
   value: Color
 }

/@react-stately/color:ColorFieldState

 ColorFieldState {
   colorValue: Color | null
   commit: () => void
   commitValidation: () => void
   decrement: () => void
   decrementToMin: () => void
+  defaultColorValue: Color | null
   displayValidation: ValidationResult
   increment: () => void
   incrementToMax: () => void
   inputValue: string
   realtimeValidation: ValidationResult
   resetValidation: () => void
+  setColorValue: (Color | null) => void
   setInputValue: (string) => void
   updateValidation: (ValidationResult) => void
   validate: (string) => boolean
 }

/@react-stately/color:ColorChannelFieldState

 ColorChannelFieldState {
   canDecrement: boolean
   canIncrement: boolean
   colorValue: Color
   commit: () => void
   commitValidation: () => void
   decrement: () => void
   decrementToMin: () => void
+  defaultColorValue: Color | null
+  defaultNumberValue: number
   displayValidation: ValidationResult
   increment: () => void
   incrementToMax: () => void
   inputValue: string
   maxValue?: number
   minValue?: number
   numberValue: number
   realtimeValidation: ValidationResult
   resetValidation: () => void
+  setColorValue: (Color | null) => void
   setInputValue: (string) => void
   setNumberValue: (number) => void
   updateValidation: (ValidationResult) => void
   validate: (string) => boolean

@react-stately/combobox

/@react-stately/combobox:ComboBoxState

 ComboBoxState <T> {
   close: () => void
   collection: Collection<Node<T>>
   commit: () => void
   commitValidation: () => void
+  defaultInputValue: string
+  defaultSelectedKey: Key | null
   disabledKeys: Set<Key>
   displayValidation: ValidationResult
   focusStrategy: FocusStrategy | null
   inputValue: string
   isOpen: boolean
   open: (FocusStrategy | null, MenuTriggerAction) => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   revert: () => void
   selectedItem: Node<T> | null
   selectedKey: Key | null
   selectionManager: SelectionManager
   setFocused: (boolean) => void
   setInputValue: (string) => void
   setOpen: (boolean) => void
   setSelectedKey: (Key | null) => void
   toggle: (FocusStrategy | null, MenuTriggerAction) => void
   updateValidation: (ValidationResult) => void
 }

@react-stately/datepicker

/@react-stately/datepicker:DateFieldState

 DateFieldState {
   calendar: Calendar
   clearSegment: (SegmentType) => void
   commitValidation: () => void
   confirmPlaceholder: () => void
   dateFormatter: DateFormatter
   dateValue: Date
   decrement: (SegmentType) => void
   decrementPage: (SegmentType) => void
+  defaultValue: DateValue | null
   displayValidation: ValidationResult
   formatValue: (FieldOptions) => string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   incrementPage: (SegmentType) => void
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   isRequired: boolean
   maxGranularity: 'year' | 'month' | Granularity
   realtimeValidation: ValidationResult
   resetValidation: () => void
   segments: Array<DateSegment>
   setSegment: (SegmentType, number) => void
   setValue: (DateValue | null) => void
   updateValidation: (ValidationResult) => void
   value: DateValue | null
 }

/@react-stately/datepicker:DatePickerState

 DatePickerState {
   close: () => void
   commitValidation: () => void
   dateValue: DateValue | null
+  defaultValue: DateValue | null
   displayValidation: ValidationResult
   formatValue: (string, FieldOptions) => string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   isInvalid: boolean
   isOpen: boolean
   open: () => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   setDateValue: (DateValue) => void
   setOpen: (boolean) => void
   setTimeValue: (TimeValue) => void
   setValue: (DateValue | null) => void
   timeValue: TimeValue | null
   toggle: () => void
   updateValidation: (ValidationResult) => void
   value: DateValue | null
 }

/@react-stately/datepicker:DateRangePickerState

 DateRangePickerState {
   close: () => void
   commitValidation: () => void
   dateRange: RangeValue<DateValue | null> | null
+  defaultValue: DateRange | null
   displayValidation: ValidationResult
   formatValue: (string, FieldOptions) => {
     start: string
   end: string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   hasTime: boolean
   isInvalid: boolean
   isOpen: boolean
   open: () => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   setDate: ('start' | 'end', DateValue | null) => void
   setDateRange: (DateRange) => void
   setDateTime: ('start' | 'end', DateValue | null) => void
   setOpen: (boolean) => void
   setTime: ('start' | 'end', TimeValue | null) => void
   setTimeRange: (TimeRange) => void
   setValue: (DateRange | null) => void
   timeRange: RangeValue<TimeValue | null> | null
   toggle: () => void
   updateValidation: (ValidationResult) => void
   value: RangeValue<DateValue | null>
 }

/@react-stately/datepicker:TimeFieldState

 TimeFieldState {
   calendar: Calendar
   clearSegment: (SegmentType) => void
   commitValidation: () => void
   confirmPlaceholder: () => void
   dateFormatter: DateFormatter
   dateValue: Date
   decrement: (SegmentType) => void
   decrementPage: (SegmentType) => void
+  defaultValue: DateValue | null
   displayValidation: ValidationResult
   formatValue: (FieldOptions) => string
   getDateFormatter: (string, FormatterOptions) => DateFormatter
   granularity: Granularity
   incrementPage: (SegmentType) => void
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   isRequired: boolean
   maxGranularity: 'year' | 'month' | Granularity
   realtimeValidation: ValidationResult
   resetValidation: () => void
   segments: Array<DateSegment>
   setSegment: (SegmentType, number) => void
   setValue: (DateValue | null) => void
   timeValue: Time
   updateValidation: (ValidationResult) => void
   value: DateValue | null
 }

@react-stately/numberfield

/@react-stately/numberfield:NumberFieldState

 NumberFieldState {
   canDecrement: boolean
   canIncrement: boolean
   commit: () => void
   commitValidation: () => void
   decrement: () => void
   decrementToMin: () => void
+  defaultNumberValue: number
   displayValidation: ValidationResult
   increment: () => void
   incrementToMax: () => void
   inputValue: string
   minValue?: number
   numberValue: number
   realtimeValidation: ValidationResult
   resetValidation: () => void
   setInputValue: (string) => void
   setNumberValue: (number) => void
   updateValidation: (ValidationResult) => void
   validate: (string) => boolean
 }

@react-stately/radio

/@react-stately/radio:RadioGroupState

 RadioGroupState {
   commitValidation: () => void
+  defaultSelectedValue: string | null
   displayValidation: ValidationResult
   isDisabled: boolean
   isInvalid: boolean
   isReadOnly: boolean
   lastFocusedValue: string | null
   realtimeValidation: ValidationResult
   resetValidation: () => void
   selectedValue: string | null
   setLastFocusedValue: (string | null) => void
   setSelectedValue: (string | null) => void
   updateValidation: (ValidationResult) => void
 }

@react-stately/select

/@react-stately/select:SelectState

 SelectState <T> {
   close: () => void
   collection: Collection<Node<T>>
   commitValidation: () => void
+  defaultSelectedKey: Key | null
   disabledKeys: Set<Key>
   displayValidation: ValidationResult
   focusStrategy: FocusStrategy | null
   isFocused: boolean
   open: (FocusStrategy | null) => void
   realtimeValidation: ValidationResult
   resetValidation: () => void
   selectedItem: Node<T> | null
   selectedKey: Key | null
   selectionManager: SelectionManager
   setFocused: (boolean) => void
   setOpen: (boolean) => void
   setSelectedKey: (Key | null) => void
   toggle: (FocusStrategy | null) => void
   updateValidation: (ValidationResult) => void
 }

@react-stately/slider

/@react-stately/slider:SliderState

 SliderState {
   decrementThumb: (number, number) => void
+  defaultValues: Array<number>
   focusedThumb: number | undefined
   getFormattedValue: (number) => string
   getPercentValue: (number) => number
   getThumbMaxValue: (number) => number
   getThumbPercent: (number) => number
   getThumbValue: (number) => number
   getThumbValueLabel: (number) => string
   getValuePercent: (number) => number
   incrementThumb: (number, number) => void
   isDisabled: boolean
   isThumbDragging: (number) => boolean
   isThumbEditable: (number) => boolean
   orientation: Orientation
   pageSize: number
   setFocusedThumb: (number | undefined) => void
   setThumbDragging: (number, boolean) => void
   setThumbEditable: (number, boolean) => void
   setThumbPercent: (number, number) => void
   setThumbValue: (number, number) => void
   step: number
   values: Array<number>
 }

@react-stately/toggle

/@react-stately/toggle:ToggleState

 ToggleState {
+  defaultSelected: boolean
   isSelected: boolean
   setSelected: (boolean) => void
   toggle: () => void
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

React 19 Actions + RAC Form aren't working properly due to automatic form reset
3 participants