Given the following typed React component using generic type arguments, how would I go about wrapping it in React's new forwardRef
API?
type Props<T> = {
forwardedRef?: Ref<HTMLInputElement>
...
}
class GenericComponent<T> extends Component<Props<T>> {
...
}
const ComponentWithRef = forwardRef<HTMLInputElement, Props<T>>((props, ref) => (
<StringInput<T> {...props} forwardedRef={ref} />
))
The above approach has no way to define the T
generic.
React forwardRef is a method that allows parent components pass down (i.e., “forward”) refs to their children. Using forwardRef in React gives the child component a reference to a DOM element created by its parent component. This then allows the child to read and modify that element anywhere it is being used.
On this case, we need to change the Input Component to use the forwardRef. import React, { forwardRef } from "react"; const Input = (props, ref) => <input ref={ref} type="text" style={style} />; export default forwardRef(Input);
forwardRef() which means we have to apply the HOC before React.
So, to broaden the question some, this is really a question about preserving generic types in higher order functions. The following usage of forwardRef
will properly typecheck (in 3.0.1
)
const SelectWithRef = forwardRef(<Option extends string>(props: Props<Option>, ref?: Ref<HTMLSelectElement>) =>
<Select<Option> {...props} forwardedRef={ref} />);
But, the Option
generic is immediately resolved to string
, rather than remaining as a generic. As such, the following does not typecheck
const onChange: (value: 'one' | 'two') => void = (value) => console.log(value);
<SelectWithRef<'one' | 'two'>
^^^^^^^^^^^^^^^ [ts] Expected 0 type arguments, but got 1
value="a"
options={['one', 'two']}
onChange={onChange}
^^^^^^^^^^ [ts] Type 'string' is not assignable to type '"one" | "two"'
/>
The relevant issue is tracked in this Typescript issue ticket.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With