Mismatch in type definitions of ref prop and useRef hook
See original GitHub issueDo 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
Issue Analytics
- State:
- Created 4 years ago
- Comments:5
No.
The key difference is what
ref.current
will be before the image has been set. The table below illustrates it: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 yourref.current
is the same thing before mount as it is after unmount.Aaaaah, that it makes sense. Thank you for the quick reply!