4

I'm using a ref on a View. Typescript is giving me an error "Object is possibly 'null'". What is the correct typing for a ref used on a View? Specifically I'm using an Animated.View but I don't think that makes a difference.

Other answers on here are for ReactJS(web) and use const overlayEl = useRef<HTMLDivElement>(null); but I'm looking for an answer for React Native.

const Component = () => {
  const ref = React.useRef(null);

  React.useLayoutEffect(()=>{
    console.log(ref.current.clientHeight); 
    // ^ Error: "Object is possibly null" on the `ref.current` portion
  },[]);

  return (
    <Animated.View ref={ref} style={{height: 100}}></Animated.View>
  );
}

Things I tried:

const ref = React.useRef<React.FunctionComponent>(null);
const ref = React.useRef<React.ReactElement>(null);
const ref = React.useRef<React.MutableRefObject<null>>(null);
const ref = React.useRef(null) as React.MutableRefObject<null>;
console.log(ref?.current?.clientHeight); 
// ^ Error: Property clientHeight does not exist on type 'never'

The only thing that works is this, but this isn't really a proper fix

  React.useLayoutEffect(()=>{
    const current = ref?.current || { clientHeight: 0 }; 
    console.log(ref.current.clientHeight);
  },[]);
9
  • The only thing that works is this, but this isn't really a proper fix What do you consider to be a proper fix? Commented Dec 1, 2021 at 22:23
  • If there's a way to resolve it by setting the type correctly in the useRef declaration then to me, that's the proper fix. I assume I simply don't know what the proper typing is. If there isn't a typing to resolve it, then I guess what I wrote above is the proper fix. Commented Dec 1, 2021 at 22:30
  • 2
    Well useRef(null) effectively returns a ref which has a null current property, TypeScript warns you about it before you execute the code so you have to adapt it with a null check or an optional chaining operator just like you did Commented Dec 1, 2021 at 22:33
  • I see. And putting useRef() without the null makes no difference right since it's still undefined. I can accept your comment as the answer if you respond with that. Thanks Commented Dec 1, 2021 at 22:37
  • useLayoutEffect runs before render so that's why your ref is null. Is there any reason to use React.useLayoutEffect instead of React.useEffect Commented Dec 1, 2021 at 23:04

2 Answers 2

2

Here is how useRef is being typed in React:

function useRef<T>(initialValue: T): MutableRefObject<T>;

interface MutableRefObject<T> {
    current: T;
}

That means once the MutableRefObject is being typed, it always keeps its type so you have to type it properly with the angle brackets:

const ref = React.useRef<React.ElementRef<typeof View> | null>(null);
Sign up to request clarification or add additional context in comments.

2 Comments

After changing it to a View and defining the ref as you stated, It still errors with "Property clientHeight does not exist on property View". I guess I just need to define it explicitly as you noted in the comments. Alternatively, what also makes it go away, is const ref= React.useRef<any>(null); as per this question but some may question how proper that is. I'm okay to accept that at this stage given everything else we discussed
This is why I asked you if clientHeight existed in React Native because I think it doesn't. You can stick with the any solution but you have to be aware that the any type is a workaround, it just completely disables TypeScript's type checkings, just like you were writing plain JavaScript
0

I dont think its really a TypeScript issue, but more of an initialization problem. When you try to access your ref you do so in the way you would access an object and its null and not an object and thus throws the error you get. You could either verify the ref isnt null, or initialize it to some object so that you can properly query its properties:

// this
const ref = React.useRef({});



// or this
const ref = React.useRef(null);
React.useLayoutEffect(()=>{
    if(ref.current !== null){
       //do stuff
    }
  },[]);

1 Comment

This makes sense. but when I put it inside if ( ref.current !== null ) {...} then I get the error: "Property 'clientHeight' does not exist on type never"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.