@ariakit/react-utils
Important: This package is an internal dependency of Ariakit and does not follow semantic versioning, meaning breaking changes may occur in patch and minor versions. You probably want to use @ariakit/react instead.
Shared React utilities used by Ariakit React packages.
Contents
Installation
npm i @ariakit/react-utils
Usage
Import helpers from the package root:
import { useEvent } from "@ariakit/react-utils";
This package is ESM-only and exposes a single public entrypoint.
API reference
Hooks
React hooks for refs, events, ids, effects, and element metadata.
useSafeLayoutEffect
const useSafeLayoutEffect: typeof React.useLayoutEffect;
React.useLayoutEffect that fallbacks to React.useEffect on server side.
useInitialValue
function useInitialValue<T>(value: T | (() => T)): T;
Returns a value that never changes even if the argument is updated.
Example:
function Component({ prop }) {
const initialProp = useInitialValue(prop);
}
useLiveRef
function useLiveRef<T>(value: T): RefObject<T>;
Creates a React.RefObject that is constantly updated with the incoming value.
Example:
function Component({ prop }) {
const propRef = useLiveRef(prop);
}
useEvent
function useEvent<T extends AnyFunction>(callback?: T): T;
Creates a stable callback function that has access to the latest state and can be used within event handlers and effect callbacks. Throws when used in the render phase.
Example:
function Component(props) {
const onClick = useEvent(props.onClick);
React.useEffect(() => {}, [onClick]);
}
useTransactionState
function useTransactionState<T>(
callback?: ((state: SetStateAction<T | null>) => void) | null,
): readonly [T | null, React.Dispatch<SetStateAction<T | null>>];
Creates a React state that calls a callback function whenever the state changes and rolls back to the previous state on cleanup.
useMergeRefs
function useMergeRefs(
...refs: Array<Ref<any> | undefined>
): ((value: unknown) => (() => void) | undefined) | undefined;
Merges React Refs into a single memoized function ref so you can pass it to an element.
Example:
const Component = React.forwardRef((props, ref) => {
const internalRef = React.useRef();
return <div {...props} ref={useMergeRefs(internalRef, ref)} />;
});
useId
function useId(defaultId?: string): string | undefined;
Generates a unique ID. Uses React's useId if available.
useDeferredValue
function useDeferredValue<T>(value: T): T;
Uses React's useDeferredValue if available.
useTagName
function useTagName(
refOrElement?: RefObject<HTMLElement | null> | HTMLElement | null,
type?: string | ComponentType,
): string | undefined;
Returns the tag name by parsing an element ref.
Example:
function Component(props) {
const ref = React.useRef();
const tagName = useTagName(ref, "button"); // div
return <div ref={ref} {...props} />;
}
useAttribute
function useAttribute(
refOrElement: RefObject<HTMLElement | null> | HTMLElement | null,
attributeName: string,
defaultValue?: string,
): string | undefined;
Returns the attribute value of an element.
Example:
function Component(props) {
const ref = React.useRef();
const role = useAttribute(ref, "role", props.role);
return <div ref={ref} {...props} />;
}
useUpdateEffect
function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void;
A React.useEffect that will not run on the first render.
useUpdateLayoutEffect
function useUpdateLayoutEffect(
effect: EffectCallback,
deps?: DependencyList,
): void;
A React.useLayoutEffect that will not run on the first render.
useForceUpdate
function useForceUpdate(): [never[], React.ActionDispatch<[]>];
A React hook similar to useState and useReducer, but with the only purpose of re-rendering the component.
useBooleanEvent
function useBooleanEvent<T extends unknown[]>(
booleanOrCallback: boolean | ((...args: T) => boolean),
): (...args: T) => boolean;
Returns an event callback similar to useEvent, but this also accepts a boolean value, which will be turned into a function.
useWrapElement
function useWrapElement<P>(
props: P & { wrapElement?: WrapElement },
callback: WrapElement,
deps: DependencyList = [],
): P & { wrapElement: WrapElement };
Returns props with an additional wrapElement prop.
usePortalRef
function usePortalRef(
portalProp = false,
portalRefProp?:
RefCallback<HTMLElement> | MutableRefObject<HTMLElement | null>,
): {
portalRef: ((value: unknown) => (() => void) | undefined) | undefined;
portalNode: HTMLElement | null;
domReady: true | HTMLElement | null;
};
Merges the portalRef prop and returns a domReady to be used in the components that use Portal underneath.
useMetadataProps
function useMetadataProps<T, K extends keyof any>(
props: { onLoadedMetadataCapture?: AnyFunction & { [key in K]?: T } },
key: K,
value: T,
): readonly [
(AnyFunction & { [key in K]?: T | undefined })[K] | undefined,
{ readonly onLoadedMetadataCapture: any },
];
A hook that passes metadata props around without leaking them to the DOM.
useIsMouseMoving
function useIsMouseMoving(): () => boolean;
Returns a function that checks whether the mouse is moving.
General utilities
Helpers for working with refs, elements, and props.
setRef
function setRef<T>(
ref: RefCallback<T> | MutableRefObject<T> | null | undefined,
value: T,
): void | (() => void);
Sets both a function and object React ref.
Returns a callback ref cleanup function when one is provided.
isValidElementWithRef
function isValidElementWithRef<P extends { ref?: Ref<any> }>(
element: unknown,
): element is ReactElement<P> & { ref?: Ref<any> };
Checks if an element is a valid React element with a ref.
getRefProperty
function getRefProperty(element: unknown): Ref<any> | undefined;
Gets the ref property from a React element.
mergeProps
function mergeProps<T extends HTMLAttributes<any>>(base: T, overrides: T): T;
Merges two sets of props.
System utilities
Helpers for creating and composing Ariakit React components.
forwardRef
function forwardRef<T extends React.FC<any>>(render: T): T;
The same as React.forwardRef but passes the ref as a prop and returns a component with the same generic type.
Props holding undefined are dropped, so passing one behaves the same as omitting it and the component keeps the value it computes for itself.
memo
function memo<T extends React.FC<any>>(
Component: T,
propsAreEqual?: (
prevProps: Readonly<React.ComponentPropsWithoutRef<T>>,
nextProps: Readonly<React.ComponentPropsWithoutRef<T>>,
) => boolean,
): T;
The same as React.memo but returns a component with the same generic type.
createElement
function createElement(
Type: React.ElementType,
props: Props<React.ElementType, Options>,
): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
Creates a React element that supports the render and wrapElement props.
createHook
function createHook<
T extends React.ElementType,
P extends AnyObject = EmptyObject,
>(useProps: (props: Props<T, P>) => HTMLProps<T, P>): Hook<T, P>;
Creates a component hook that accepts props and returns props so they can be passed to a React element.
createStoreContext
type StoreProvider<T extends Store> = React.ComponentType<{
value: T | undefined;
children?: React.ReactNode;
}>;
function createStoreContext<T extends Store>(
providers: StoreProvider<T>[] = [],
scopedProviders: StoreProvider<T>[] = [],
): {
context: React.Context<T | undefined>;
scopedContext: React.Context<T | undefined>;
useContext: () => T | undefined;
useScopedContext: (onlyScoped?: boolean) => T | undefined;
useProviderContext: () => T | undefined;
ContextProvider: (
props: React.ComponentPropsWithoutRef<React.Provider<T | undefined>>,
) => React.JSX.Element;
ScopedContextProvider: (
props: React.ComponentPropsWithoutRef<React.Provider<T | undefined>>,
) => React.JSX.Element;
};
Creates an Ariakit store context with hooks and provider components.
Type utilities
Shared types for Ariakit React components.
RenderProp
type RenderProp<P = React.HTMLAttributes<any> & { ref?: React.Ref<any> }> = (
props: P,
) => React.ReactNode;
Render prop type.
Example:
const children: RenderProp = (props) => <div {...props} />;
WrapElement
type WrapElement = (element: React.ReactElement) => React.ReactElement;
The wrapElement prop.
Options
interface Options {
wrapElement?: WrapElement;
/**
* Allows the component to be rendered as a different HTML element or React
* component. The value can be a React element or a function that takes in the
* original component props and gives back a React element with the props
* merged.
*
* Some Ariakit components detect the type of the underlying element when
* they mount. If the render element's type may change while the component
* is mounted, pass a
* [`key`](https://react.dev/learn/preserving-and-resetting-state) prop that
* changes with the element type so React remounts the component with the
* new element. Remounting resets uncontrolled state, so keep the relevant
// ... 11 more lines
* for more details.
*/
render?: RenderProp | React.ReactElement;
}
Custom props including the render prop.
HTMLProps
type HTMLProps<
T extends React.ElementType,
P extends AnyObject = EmptyObject,
> = Omit<React.ComponentPropsWithRef<T>, keyof P> & {
[index: `data-${string}`]: unknown;
};
HTML props based on the element type, excluding custom props.
Example:
type ButtonHTMLProps = HTMLProps<"button", { custom?: boolean }>;
Props
type Props<T extends React.ElementType, P extends AnyObject = EmptyObject> = P &
HTMLProps<T, P>;
Props based on the element type, including custom props.
Hook
type Hook<T extends React.ElementType, P extends AnyObject = EmptyObject> = <
ElementType extends React.ElementType = T,
>(
props?: Props<ElementType, P>,
) => HTMLProps<ElementType, P>;
A component hook that supports the render prop and returns HTML props based on the element type.
Example:
type UseButton = Hook<"button", { custom?: boolean }>;