Reputation: 2558
So, I've got this titleRef
const titleRef = useRef<HTMLHeadingElement | null>(null);
It's attached to this header:
<h1 ref={titleRef}>Hi!</h1>
I want to use it to do some work with styling on screen resize, like so:
if (titleRef.current.style.offsetWidth > '10px') {...}
TS doesn't like this. See, useRef(null)
means that titleRef could equal null
(which, fair enough) and so everywhere I use titleRef
, I have to account for that with something like
if (titleRef.current) {
...do the thing
}`
which gets to be a pain in the ass if titleRef
gets used a lot.
Is there more elegant way to handle this situation? Directly set titleRef
to be the <h1>
element directly in useRef
? Or, instead of using null
, pass useRef()
some "generic" HTMLHeadingElement
?
Edit: Optional chaining was the the first thing I tried, but, that doesn't appear to help:
Edit 2: adding an !
does clear the warning, but it also makes the value static and might lead to trouble, depending on your use case.
Edit 3: using optional chaining can also make the linter mad, if you're going modify titleRef.current
.
If you're not modifying the value, only reading it, then ?
should be fine, but if not...
While the answers below work some of the time, the downsides don't seem worth it, to me. For now, I'm going to stick to my if spam...
Upvotes: 8
Views: 2112
Reputation: 136
If you are not going to assign null
in the future and it is just an initial value, then you can use :
const titleRef = useRef<HTMLHeadingElement>(null!);
The exclamation mark after null
tells typescript that it is meant to be initial value and the value will most possibly change.
Check out Typescript-cheatsheets notes here
Upvotes: 8
Reputation: 55876
OK, I ended up testing this. Optional chaining can help you get rid of the if
that's bloating your code:
const myTestRef = React.useRef<IFancyRef>(null);
const handleClick = () => {
myTestRef.current?.focus();
// or
myTestRef.current!.focus(); // this assumes you KNOW that myTestRef is assigned
};
Upvotes: 4