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
The main reason that useControlledState
and similar utilities aren't exported from the monopackage is because they aren't documented, and aren't necessarily intended to be public APIs. You're right that we do prefer people to use the monopackages to avoid issues with managing package versions. I think if we do want to start exporting these from the monopackage, we'll need to solidify the APIs and document them.