I am creating a reference using the new useRef hook
const anchorEl = React.useRef<HTMLDivElement>(null)
And using like
<div style={{ width: "15%", ...flexer, justifyContent: "flex-end" }}>
<Popover
id="simple-popper"
open={open}
anchorEl={anchorEl}
onClose={() => {
setOpen(false)
}}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
<Typography>The content of the Popover.</Typography>
</Popover>
</div>
<div ref={anchorEl} >
...
but I get this error
TS2322: Type 'MutableRefObject<HTMLDivElement>' is not assignable to type 'HTMLElement | ((element: HTMLElement) => HTMLElement)'.
Type 'MutableRefObject<HTMLDivElement>' is not assignable to type '(element: HTMLElement) => HTMLElement'.
Type 'MutableRefObject<HTMLDivElement>' provides no match for the signature '(element: HTMLElement): HTMLElement'.
Version: typescript 3.2.2, tslint 5.12.0
To use useRef with TypeScript, it is actually pretty easy, all you need to do is provide the type that you want to the function via open and closed chevrons like you would with other React hooks like so: const myRef = useRef<number>(0) .
const inputRef = useRef() creates a reference to hold the input element. inputRef is then assigned to ref attribute of the input field: <input ref={inputRef} type="text" /> . React then, after mounting, sets inputRef. current to be the input element.
You can use hooks in . ts files. . tsx is if you need to use JSX expressions.
The useRef is a hook that allows to directly create a reference to the DOM element in the functional component. Syntax: const refContainer = useRef(initialValue); The useRef returns a mutable ref object.
anchorEl
variable is ref object, an object that has only current
property. It's unknown how Popover
works but, but it expects an element as anchorEl
prop, not a ref.
It should be:
<Popover
id="simple-popper"
open={open}
anchorEl={anchorEl.current}
If <Popover
and <div ref={anchorEl} >
are siblings like it's shown, a ref won't be ready to use at the moment when it's passed as a prop. In this case a component needs to be re-rendered on mount:
const [, forceUpdate] = useState(null);
useEffect(() => {
forceUpdate({});
}, []);
...
{ anchorEl.current && <Popover
id="simple-popper"
open={open}
anchorEl={anchorEl.current}
...
}
<div ref={anchorEl} >
In case <div ref={anchorEl} >
doesn't have to be rendered to DOM, it could be
<Popover
id="simple-popper"
open={open}
anchorEl={<div/>}
The necessity to render a component twice and use forceUpdate
workaround suggests that this could be done in a better way. The actual problem here is that Popover
accepts an element as a prop, while accepting refs is common in React.
At this point ref object has no benefits. Ref callback can be used with useState
instead, state update function is callback that receives new state as an argument and it doesn't cause additional updates if it receives the same state (DOM element):
const [anchorEl, setAnchorEl] = useState<HTMLDivElement>(null);
...
{ anchorEl && <Popover
id="simple-popper"
open={open}
anchorEl={anchorEl}
...
}
<div ref={setAnchorEl} >
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With