Does anyone knows hows the right approach to pass callback references using react hooks. I'm trying to convert a modal that is built in a class component, to a hook component, but I'm not sure what's the correct way to do it.
onOpen = () => {
this.setState({ isOpen: true }, () => {
// Ref for the button
this.closeButtonNode.focus();
});
this.toggleScrollLock();
};
And this is how I pass the the reference in the code
<ModalContent
buttonRef={(n) => {
this.closeButtonNode = n;
}}
{// More props...}
/>
And the modal content component has the buttonRef like this
<button
type="button"
className="close"
aria-labelledby="close-modal"
onClick={onClose}
ref={buttonRef}
>
<span aria-hidden="true">×</span>
</button>
So when the modal pops I was able to get focus in my button close, with hooks, the only way I managed to replicate the behavior is to add an useEffect hook that listen to the isOpen state like this:
useEffect(() => {
if (isOpen) closeButtonNode.current.focus();
}, [isOpen]);
const onOpen = () => {
setIsOpen(true);
toggleScrollLock();
};
And this is how I pass the prop
const closeButtonNode = useRef(null);
return (
<ModalContent
buttonRef={closeButtonNode}
{// More props...}
/>
)
And I just use it like a regular ref, without passing a callback function, this works but I wonder why it works that way and why I cannot set the focus on the onOpen function like the class based component.
This is the sandbox if you want to check the full code. https://codesandbox.io/s/hooks-modal-vs-class-modal-bdjf0
Why I cannot set the focus on the
onOpen
function like the class based component
Because when onOpen
function get called open
toggle still false
and it will get updated after the modal is already opened. Please note that useState doesn't have a second argument (callback) like setState
in class based component as you have done to set the focus. That why you needed to use useEffect
.
You can test that by setting a delay using setTimeout
after you set open
to true like so:
const onOpen = () => {
setIsOpen(true);
setTimeout(() => closeButtonNode.current.focus())
};
Although, your approach using useEffect
would be maybe better option.
codeSandbox example.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.