website/pages/docs/custom-hooks.mdx
<PageCard>
# Custom Hooks
You can build your own custom Hook to perform unique logic that
is not currently exported by the library.
<ShowFor packages={['react-dom']}>
<PackageLimited>@floating-ui/react only</PackageLimited>
</ShowFor>
</PageCard>
The Hooks exported by the library essentially just return HTML
props (`onClick{:.keyword}`, `aria-describedby{:.keyword}`, etc.)
inside a prop getter key, which get merged. You can do the same
thing.
<Notice>
The library is fully tree-shakeable, so we can add new Hooks
for specific commonly requested features. If you have ideas for
new Hooks or functionality, don't hesitate to open a new issue
or discussion on the [GitHub
repo](https://github.com/floating-ui/floating-ui)!
</Notice>
```ts
const useCustomLogic = (
context: FloatingContext,
): ElementProps => {
const referenceProps = useMemo(
() => ({
// React.HTMLProps
onClick: () => console.log('clicked'),
}),
[],
);
const floatingProps = useMemo(
() => ({
// React.HTMLProps
}),
[],
);
const itemProps = useMemo(
() => ({
// React.HTMLProps
}),
[],
);
// All 3 of these properties are optional.
return useMemo(
() => ({
reference: referenceProps,
floating: floatingProps,
item: itemProps,
}),
[referenceProps, floatingProps, itemProps],
);
};
```
## Communicating between Hooks
Interaction Hooks are decoupled, so passing the shared context
object as a first argument is how they communicate with each
other.
It has an event emitter attached:
```js
const {context} = useFloating();
useEffect(() => {
const handleEvent = () => {};
context.events.on('name', handleEvent);
return () => {
context.events.off('name', handleEvent);
};
}, [context.events]);
return (
<div
onClick={() => {
context.events.emit('name', {foo: 'bar'});
}}
/>
);
```
And also a mutable ref to pass state variables around Hooks:
```js
const {context} = useFloating();
useEffect(() => {
context.dataRef.current.foo = 'bar';
}, [context]);
```