Confusión de TypeScript React.FC <Props>
Estoy aprendiendo TypeScript y algunas partes me resultan confusas. Un bit está debajo:
interface Props {
name: string;
}
const PrintName: React.FC<Props> = (props) => {
return (
<div>
<p style={{ fontWeight: props.priority ? "bold" : "normal" }}>
{props.name}
</p>
</div>
)
}
const PrintName2 = (props: Props) => {
return (
<div>
<p style={{ fontWeight: props.priority ? "bold" : "normal" }}>
{props.name}
</p>
</div>
)
}
Para los dos componentes funcionales anteriores, veo que TypeScript genera el mismo código JS. El PrintName2
componente me parece más simplificado en cuanto a legibilidad. Me pregunto cuál es la diferencia entre las dos definiciones y si alguien está usando el segundo tipo de componente React.
Gracias por todas las respuestas. Son correctos pero estaba buscando una versión más detallada. Investigué un poco más y encontré esto en React+TypeScript Cheatsheets en GitHub.
Componentes de funciones
Estos pueden escribirse como funciones normales que toman un argumento de accesorios y devuelven un elemento JSX.
type AppProps = { message: string }; /* could also use interface */
const App = ({ message }: AppProps) => <div>{message}</div>;
Qué pasa React.FC
/ React.FunctionComponent
? También puedes escribir componentes con React.FunctionComponent
(o la abreviatura React.FC
):
const App: React.FC<{ message: string }> = ({ message }) => (
<div>{message}</div>
);
Algunas diferencias con la versión "función normal":
Proporciona verificación de tipo y autocompletar para propiedades estáticas como displayName
, propTypes
y defaultProps
. Sin embargo, actualmente existen problemas conocidos al usar defaultProps
con React.FunctionComponent
. Consulte este número para obtener más detalles; desplácese hacia abajo hasta nuestra defaultProps
sección para obtener recomendaciones de escritura allí.
Proporciona una definición implícita de hijos (ver más abajo); sin embargo, hay algunos problemas con el tipo de hijos implícitos (por ejemplo, DefinitelyTyped#33006), y de todos modos podría considerarse un mejor estilo ser explícito acerca de los componentes que consumen hijos.
const Title: React.FunctionComponent<{ title: string }> = ({
children,
title
}) => <div title={title}>{children}</div>;
En el futuro, puede marcar automáticamente los accesorios como de solo lectura, aunque eso es un punto discutible si el objeto de accesorios está desestructurado en la lista de parámetros.
React.FunctionComponent
es explícito sobre el tipo de retorno, mientras que la versión de la función normal es implícita (o necesita anotaciones adicionales).
En la mayoría de los casos, hay muy poca diferencia qué sintaxis se utiliza, pero la
React.FC
sintaxis es un poco más detallada sin proporcionar una ventaja clara, por lo que se le dio prioridad a la sintaxis de "función normal".
React.FC
No es la forma preferible de escribir un componente de React, aquí hay un enlace .
Yo personalmente uso este tipo:
const Component1 = ({ prop1, prop2 }): JSX.Element => { /*...*/ }
Breve lista de React.FC
desventajas:
- Proporciona una definición implícita de hijos, incluso si su componente no necesita tener hijos. Eso podría causar un error.
- No admite genéricos.
- No funciona correctamente con
defaultProps
.
Mejor solución:
El segundo enfoque + un tipo de retorno
const PrintName2 = ({ prop1, prop2 }: Props): JSX.Element => { /** */}
Esto te da control total sobre los accesorios y es más explícito (no hay magia oculta).
Enlace a GitHub PR para eliminar React.FC
Kent C Dodds tiene algunas ideas sobre por qué esto está aquí
Solución subóptima:
La primera versión (React.FC) agregará algunos tipos: provienen de React Typings
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement | null;
propTypes?: WeakValidationMap<P>;
contextTypes?: ValidationMap<any>;
defaultProps?: Partial<P>;
displayName?: string;
}
Este enfoque es útil por varias razones, pero una obvia es que si su componente tiene hijos, entonces no necesita agregar manualmente un children
accesorio. No es genial porque hay problemas con los accesorios predeterminados y muchos componentes no tienen hijos.
Dado que está utilizando React y TypeScript, siempre debe usar el primer patrón, ya que garantizará que su componente tenga un tipo más estricto, ya que implica que será PrintName
del tipo React Functional Component y requiere accesorios de tipo Props
.
const PrintName: React.FC<Props>
Puede leer la definición completa de la interfaz para componentes funcionales en el repositorio de mecanografía de React TypeScript .
El segundo ejemplo que proporcionó no proporciona ningún tipo de tipificación, excepto que es una función que toma un conjunto de parámetros de tipo Props
y que puede devolver cualquier cosa en general.
Por lo tanto, escribir
const PrintName2 = (props:Props)
es similar a
const PrintName2: JSX.Element = (props:Props)
ya que TypeScript definitivamente no puede inferir automáticamente que es un componente funcional.