react-spectrum
react-spectrum copied to clipboard
Export useControlledState from react-stately (and/or react-aria-components).
Provide a general summary of the feature here
The useControlledState
hook from @react-stately/utils
is very helpful in creating reusable components, especially when building on top of React Aria Components. You can currently access useControlledState
using import { useControlledState } from '@react-stately/utils';
, but that import feels a bit like using undocumented internals. I am not sure what the intended separation is between the namespaced @react-*
packages and the non-namespaced packages, but it would be convenient if they exposed the same exports.
๐ค Expected Behavior?
One of the following imports works:
import { useControlledState } from 'react-stately';
import { useControlledState } from 'react-aria-components';
๐ฏ Current Behavior
useControlledState
is only available using import { useControlledState } from '@react-stately/utils';
.
๐ Possible Solution
Augment the react-stately
or react-aria-components
main index file (or both) to export useControlledState
.
useControlledState
is actually one example of a few hooks that I've found helpful, but I am not sure if there is a reason it's not exported from a non-namespaced package. useDescription
from @react-aria/utils
is another hook that I have found helpful.
I don't know if a goal of react-aria-components
is to re-export everything available in react-aria
and react-stately
. For managing package versions in apps, it seems beneficial to only have to install one "monopackage", rather than worry about if the version of @react-stately/utils
in package.json is different from the version used in react-aria-components
, etc.
๐ฆ Context
One of my use cases for useControlledState
is creating a wrapper around DateRangePicker that uses values that can be tagged as a preset date range. For example, something like:
// Details omitted here, but basically I am overwriting the value, defaultValue, and onChange props.
type PresetRangeValueProps<T extends DateValue, S extends string> = {
defaultValue?: PresetRangeValue<T, S> | null;
onChange?: (value: PresetRangeValue<T, S> | null) => void;
presets: readonly PresetDateRange<T, S>[];
value?: PresetRangeValue<T, S> | null;
};
// Merge from type-fest.
type PresetRangePickerProps<
T extends DateValue,
S extends string,
> = Merge<
AriaDateRangePickerProps<T>,
PresetRangeValueProps<T, S>
>;
function PresetRangePicker<T extends DateValue, S extends string>(
{
defaultValue,
onChange,
presets,
value: propsValue,
...props
}: PresetRangePickerProps<T, S>,
) {
const [value, setValue] = useControlledState(
propsValue,
defaultValue || null,
onChange,
);
// ...truncated
useControlledState
allows me to make PresetRangePicker
either controlled or uncontrolled for flexibility and more closely mimic the behavior of DateRangePicker.
๐ป Examples
No response
๐งข Your Company/Team
No response
๐ท Tracking Issue
No response