I'm trying to build and type a HOC which just wraps a component in an ApolloProvider. I would like to be able to forward the ref on to the wrapped component. However, when I try and pass props along in the forwardRef component I'm getting type errors
Somewhere along my research spree I stumbled upon an answer that talked about generics being the issue.
const withProvider = function<P>(WrappedComponent: React.ComponentClass<P>) {
type Props = P & { forwardedRef?: React.Ref<any> }
class WithProvider extends React.Component<Props> {
render() {
const { forwardedRef, ...props } = this.props
return (
<ApolloProvider client={client}>
<WrappedComponent {...props} ref={forwardedRef} />
</ApolloProvider>
)
}
}
hoistNonReactStatics(WithProvider, WrappedComponent)
return React.forwardRef((props, ref) => (
<WithProvider {...props} forwardedRef={ref} />
))
}
Gives me the error:
Type '{ forwardedRef: string | ((instance: {} | null) => any) | RefObject<{}> | undefined; children?: ReactNode; }' is not assignable to type 'Readonly<Props>'
To me these should match up and the former should be assignable to the latter. The only thing I can think of is that Readonly<Props>
contains a generic.
Can someone point me in the right direction?
The error "Argument of type is not assignable to parameter of type 'never'" occurs when we declare an empty array without explicitly typing it and attempt to add elements to it. To solve the error, explicitly type the empty array, e.g. const arr: string[] = []; .
The "Type 'string' is not assignable to type" TypeScript error occurs when we try to assign a value of type string to something that expects a different type, e.g. a more specific string literal type or an enum. To solve the error use a const or a type assertion.
While using any is certainly generic in that it will cause the function to accept any and all types for the type of arg , we actually are losing the information about what that type was when the function returns. If we passed in a number, the only information we have is that any type could be returned.
TypeScript Generics is a tool which provides a way to create reusable components. It creates a component that can work with a variety of data types rather than a single data type. It allows users to consume these components and use their own types.
Finally, I found the solution.
All you have to do is give the type of props (in
React.forwardRef
) as the type received which isP
.
return React.forwardRef((props:P, ref) => (
<WithProvider {...props} forwardedRef={ref} />
));
Complete Code:
const withProvider = function<P>(WrappedComponent: React.ComponentClass<P>) {
type Props = P & { forwardedRef?: React.Ref<any> }
class WithProvider extends React.Component<Props> {
render() {
const { forwardedRef, ...props } = this.props
return (
<ApolloProvider client={client}>
<WrappedComponent {...props} ref={forwardedRef} />
</ApolloProvider>
)
}
}
hoistNonReactStatics(WithProvider, WrappedComponent)
return React.forwardRef((props:P, ref) => (
<WithProvider {...props} forwardedRef={ref} />
))
}
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