crowhill
crowhill

Reputation: 2558

Best way to handle useRef(null) in typescript

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:

the linter still throws an error

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.

no optional left hand assignment

If you're not modifying the value, only reading it, then ? should be fine, but if not...

TL;DR

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

Answers (2)

Apoorv Kansal
Apoorv Kansal

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

Nishant
Nishant

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
  };

Here Codesandbox for you

Upvotes: 4

Related Questions