Do you want to request a feature or report a bug?
Bug?
What is the current behavior?
With Typescript strict mode turned on:
import React, { useRef } from 'react';
function Img() {
const ref = useRef<HTMLImageElement>();
return <img ref={ref} src="foobar" />
// ^^^ The type check error below
}
Type 'MutableRefObject<HTMLImageElement | undefined>' is not assignable to type 'string | ((instance: HTMLImageElement | null) => void) | RefObject<HTMLImageElement> | null | undefined'.
Type 'MutableRefObject<HTMLImageElement | undefined>' is not assignable to type 'RefObject<HTMLImageElement>'.
Types of property 'current' are incompatible.
Type 'HTMLImageElement | undefined' is not assignable to type 'HTMLImageElement | null'.
Type 'undefined' is not assignable to type 'HTMLImageElement | null'.
The expected type comes from property 'ref' which is declared here on type 'DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>'
What is the expected behavior?
I would expect an empty ref like that to be acceptable, since (from what I can see) it works fine. But Typescript complains that useRef returns undefined while the ref prop expected null.
I can "fix" it by passing null as the "default ref", like this:
const ref = useRef<HTMLImageElement>(null);
But unless there's a reason why the ref prop expects null rather than undefined, I really think it would be better if for example the ref prop on HTMLElement was adjusted to match the default return from useRef, i.e. undefined? Yes? No? Or?
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
React 16.12.0
The React team doesn't maintain (or even contribute to) the TypeScript definitions.
That being said, it looks like TypeScript is correct to warn you about this, since the default value of your ref would indeed be undefined if you did not explicitly pass a null param.
@bvaughn But does React care whether or not it is undefined or null when passed as a prop to an HTML element?
I.e. will React treat these two differently?
import React, { useRef } from 'react';
function ImgNull() {
const ref = useRef(null);
return <img ref={ref} src="foobar" />
}
function ImgUndefined() {
const ref = useRef(undefined);
return <img ref={ref} src="foobar" />
}
But does React care whether or not it is undefined or null when passed as a prop to an HTML element?
I.e. will React treat these two differently?
No.
The key difference is what ref.current will be _before_ the image has been set. The table below illustrates it:
| | before mount | after mount | after unmount |
|----------------|--------------|--------------------|---------------|
| ImgNull | null | HTMLImageElement | null |
| ImgUndefined | undefined | HTMLImageElement | null |
React sets host instance refs to null after unmount, so the TypeScript definition is trying to ensure that your ref.current is the same thing before mount as it is after unmount.
Aaaaah, that it makes sense. Thank you for the quick reply!
Most helpful comment
No.
The key difference is what
ref.currentwill be _before_ the image has been set. The table below illustrates it:| | before mount | after mount | after unmount |
|----------------|--------------|--------------------|---------------|
|
ImgNull|null|HTMLImageElement|null||
ImgUndefined|undefined|HTMLImageElement|null|React sets host instance refs to
nullafter unmount, so the TypeScript definition is trying to ensure that yourref.currentis the same thing before mount as it is after unmount.