I'm trying to pass a ref from a parent component (an EditableCell) to a Child component (Input) and use its .current.focus
property when the parent is clicked.
I'm using the forwardRef
function using typescript but I have trouble typing it correctly
interface Props {
// Some props type
}
const CellEditable = (props: Props) => {
const [isEditing, setEditing] = useState<boolean>(false)
const inputRef = useRef<HTMLInputElement>(null)
const handleClick = () => setEditing(!isEditing)
const opts = {
ref: inputRef,
value: props.value,
onChange: props.onChange
}
return (
<div onClick={handleClick}>
{
isEditing
? <InputText {...opts} />
: <div>{props.value}</div>
}
</div>
)
}
interface Props {
// Some props type
}
type Ref = HTMLInputElement
const InputText = forwardRef((props: Props, ref: Ref) => {
useEffect(() => {
ref?.current?.focus()
})
return (
<input
type='text'
ref={ref}
value={props.value}
onChange={props.onChange}
/>
)
})
With the code above, I get the following error:
Argument of type '(props: Props, ref: Ref) => JSX.Element' is not assignable to parameter of type 'ForwardRefRenderFunction<unknown, Props>'.
Types of parameters 'ref' and 'ref' are incompatible.
Type '((instance: unknown) => void) | MutableRefObject<unknown> | null' is not assignable to type 'HTMLInputElement'.
Type 'null' is not assignable to type 'HTMLInputElement'. TS2345
If I type the forwardRed
with generics, I get a different kind of error:
const InputText = forwardRef<Ref, Props>((props, ref) => { ... }
Property 'current' does not exist on type '((instance: HTMLInputElement | null) => void) | MutableRefObject<HTMLInputElement | null>'.
Property 'current' does not exist on type '(instance: HTMLInputElement | null) => void'. TS2339
Finally, typing the ref as any
give me no error.
I am new to Typescript and I don't understand the error mentioned above.
forwardRef<HTMLInputElement, Props>((props, ref) => {})
- Can you try this? – SymProperty 'current' does not exist on type '((instance: HTMLInputElement | null) => void) | MutableRefObject<HTMLInputElement | null>'.
– Rabaul