Is this a safe use of reading a ref during render?

I'm creating a popover component. I want it call a template function provided by a parent component, giving it a call back that updates some state and closes the popover. This is the basic of how I've set it up but I'm getting an eslint error about reading a ref during render.
<div ref={popoverRef} role="group" popover="auto" id={id}>
<div role="listbox">
{options.map((option) =>
optionTemplate(option, () => {
setSelectedOption(option);
popoverRef.current!.hidePopover();
}),
)}
</div>
</div>
<div ref={popoverRef} role="group" popover="auto" id={id}>
<div role="listbox">
{options.map((option) =>
optionTemplate(option, () => {
setSelectedOption(option);
popoverRef.current!.hidePopover();
}),
)}
</div>
</div>
Is there a better way to call hidePopover on the popover element?
4 Replies
choco
choco2w ago
i am not gonna lie here gang, i have no idea what this does you use {} in jsx for rendering other jsx and in the process sometimes you do some calculations if you want. Here you use {} to do some logic without returning any jsx
/usr/bin/cat
/usr/bin/cat2w ago
I dont think you can use ref like that maybe give the full component code to make it more understandable! its fells a bit cryptic!
patrickjames
patrickjames2w ago
Refs are set after the component code is ran and the element is added to the dom, so I'm guessing the reason eslint is giving you an error in that case is because it has no way of knowing when the line popoverRef.current!.hidePopover(); will actually be called. For all eslint knows, it could be called before the function / render function even returns. If that is the case, the ref will not be set yet and will be null. Eslint is not smart enough to go through your code and find out when that code will be called. If you know for sure that this line of code will only be called after the component is mounted and the ref is set, you can eslint ignore this line. I don't think there is any other way to fix this issue. but I would suggest you change the line to popoverRef.current?.hidePopover(); with the optional chaining operator ? instead of ! This is because the parent could potentially call the callback before the component is mounted, which will cause an error in your code due to the ref not being set as yet
BlueBeka
BlueBekaOP2w ago
Thanks @patrickjames I made a new post with a more full component example for those that wanted to see that: https://discord.com/channels/966627436387266600/1323491722734342174

Did you find this page helpful?