reactjs - Cómo permitir que un Componente tome un parámetro que sea ya sea un FunctionComponent o un Componente
Estoy usando Typescript y ReactJS, y soy novato. Estoy tratando de hacer algo que creo que debería ser simple, pero Typescript se está interponiendo.
Tengo dos componentes de página de React definidos así:
const HomePage: React.FunctionComponent = () => (
// stateless component, just JSX and no logic
)
class ReceiptPage extends React.Component<IReceiptPageProps> {
// has logic and state, defines render()
}
Y otro componente que debería poder tomar ambos como parámetro:
export interface IPublicRouteWrapperProps extends IPublicRouteProps {
component: typeof Component; // <---- Works for ReceiptPage, but not HomePage
layout: typeof Layout;
}
const PublicRouteWrapper: React.FunctionComponent<IPublicRouteWrapperProps> = ({
component: Component,
layout: Layout,
...rest
}) => (
<PublicRoute
{...rest}
render={props => (
<Layout>
<Component {...props} />
</Layout>
)}
/>
);
Esto funciona cuando paso el componente ReceiptPage, pero no cuando paso el componente HomePage:
<PublicRouteWrapper
title="blah"
path={`${match.url}`}
component={HomePage} // <-- error here, but works fine with ReceiptPage
exact={true}
/>
El error es:
El tipo 'FunctionComponent<{}>' no se puede asignar al tipo 'typeof Component'.
El tipo 'FunctionComponent<{}>' no proporciona coincidencia para la firma 'new(props: Readonly
): Component
'.
Y eso tiene sentido, porque HomePage no es de ese tipo.
Pero no puedo averiguar cuál debería ser. ¿Hay alguna forma de que pueda definir PublicRouteWrapper para que cualquiera de las dos páginas funcione como parámetro?
Respuesta #1
Creo que estás buscando React.ComponentType, que es una unión de ComponentClass (una interfaz para representar componentes de clase) y FunctionComponent. El tipo puede parametrizarse con el tipo de props, pero puedes elegir any para permitir todos los componentes con cualquier props. En un momento posterior, podrías aumentar la seguridad del tipo especificando el tipo real.
La interfaz IPublicRouteWrapperProps puede escribirse como:
export interface IPublicRouteWrapperProps extends IPublicRouteProps {
component: React.ComponentType<any>; // <---- Works for both ReceiptPage & HomePage
layout: typeof Layout;
}
