Component providers

Provide state to Ariakit components using a simple wrapper that supports controlled and uncontrolled props.


Component providers are optional components that act as a higher-level API on top of component stores. They wrap Ariakit components and automatically provide a store to them.

For instance, when you wrap Combobox and ComboboxPopover with ComboboxProvider, both components will be connected to the same store automatically:

If you choose not to use component providers, you will need to manually pass the store prop to each top-level component.

Managing state

Default state

Component providers can act as uncontrolled containers. In such a scenario, you can supply the initial state using props:

State setters

Component providers may also accept callbacks for state changes. These functions conventionally bear the name of the state property they modify, prefixed with the word set. They are invoked with the new state whenever an update occurs.

These state setters serve various purposes, such as updating another state, executing side effects, or implementing features like onChange, onValuesChange, onToggle, onOpenChange, and so on.

setValue={(value) => {

Controlled state

You can take full control of the state by passing the exact property, without prefixes, as a prop to the provider component. In this case, the state will be considered controlled and the component will not update the state internally. It will only call the state setter. You can use this to implement a controlled component using React.useState:

const [value, setValue] = React.useState("Banana");
<SelectProvider value={value} setValue={setValue}>

You can also receive controlled props, such as value and onChange, from a parent component and pass them directly to the provider component:


Passing a store

You can use both component providers and component stores together if you need fine-grained control over the state. In this case, you can pass the store as a prop to the provider component:

const select = useSelectStore({ defaultValue: "Banana" });
const value = select.useState("value");
<SelectProvider store={select}>

Using React Context

If you're inside a React component that's wrapped within an Ariakit component provider, you can benefit from Ariakit context hooks to access the nearest component store in the tree:

// A MenuButton that also behaves as a MenuItem when it's in a submenu
function MenuButton(props) {
const menu = useMenuContext();
const render = menu?.parent ? <Ariakit.MenuItem /> : undefined;
return <Ariakit.MenuButton {...props} render={render} />;

Follow updates

Join 1,000+ subscribers and receive monthly updates with the latest improvements on Guide.

Read latest issue

No Spam. Unsubscribe at any time.