use Custom Logic
You can build your own custom hook to perform unique logic that is not currently exported by the library.
The hooks exported by the library essentially just return HTML
props (onClick
onClick
, aria-describedby
aria-describedby
, etc.)
inside a prop getter key, which get merged. You can do the same
thing.
const useCustomLogic = (
context: FloatingContext
): ElementProps => {
// Note: all 3 of these properties are optional.
return useMemo(
() => ({
reference: {
// React.HTMLProps
onClick() {
console.log('clicked!');
},
},
floating: {
// React.HTMLProps
},
item: {
// React.HTMLProps
},
}),
[]
);
};
const useCustomLogic = (
context: FloatingContext
): ElementProps => {
// Note: all 3 of these properties are optional.
return useMemo(
() => ({
reference: {
// React.HTMLProps
onClick() {
console.log('clicked!');
},
},
floating: {
// React.HTMLProps
},
item: {
// React.HTMLProps
},
}),
[]
);
};
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:
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'});
}}
/>
);
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:
const {context} = useFloating();
useEffect(() => {
context.dataRef.current.foo = 'bar';
}, [context]);
const {context} = useFloating();
useEffect(() => {
context.dataRef.current.foo = 'bar';
}, [context]);