Controlled + TriggerRef from outside
anilanar opened this issue · comments
Our codebase @userlike has a very similar menu solution, so we had plans to reuse react-laag
and potentially contribute with bug fixes.
Now I gave it a try to replace our menu/dropdown/tooltips with react-laag
, but sadly it didn't work out.
Our "Dropdown" component takes the triggerRef
from outside (because we have a few cases in which triggerRef
is needed by others) and it can be both controlled and uncontrolled.
useToggleLayer
looks pretty good for our use cases, but it lacks a controlled mode.
Our Dropdown component has the following prop:
interface DropdownProps {
openState?: [boolean, React.Dispatch<React.SetStateAction<boolean>>];
}
It's optional. If it's not passed, Dropdown
is uncontrolled. Otherwise it's controlled.
Actually, let me give the full picture:
const openState = useState(false);
const [open, setOpen] = openState;
const triggerRef = useRef();
const layerRef = useRef();
return (
<Dropdown layer={() => <div ref={layerRef}>Hello</div>} layerRef={layerRef} triggerRef={triggerRef} openState={openState} ...>
<button ref={triggerRef} onClick={() => setOpen(open => !open)}>Toggle</button>
</Dropdown>
);
Dropdown
manages positioning the layer, closing on outside clicks etc.
And we have another component that reuses Dropdown
to attach key binds and hovers to make an accessible dropdown menu. We've noticed that Dropdown
has the best chance of reuse if layerRef, triggerRef and open state can be passed from outside.
Dropdown's behaviour is encoded inside a useDropdown
hook, so other hooks can reuse dropdown's logic.
Sorry for my lengthy/unstructured writing.
I'm having the same problem than you. I did solve this issues with the npm package react-merge-refs But I use ToggleLayer instead of useToggleLayer.
targetRef = useRef()
({ triggerRef, toggle, close, isOpen }) => (
<div ref={mergeRefs([triggerRef, targetRef])>{children}</div>
)
It's an hack solution but it should have work fine for your need.
I'm trying to push the feature even further by removing div need to hold the triggerRef sending it to the child. MergeRefs isn't doing well in this scenario, so I will try to make few edit and allow ref to be given from outside. I think it's too late for you now, but I might reference this issue later on.