Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

1.9K
Vistas
¿Cuándo usar JSX.Element vs ReactNode vs ReactElement?

Actualmente estoy migrando una aplicación React a TypeScript. Hasta ahora, esto funciona bastante bien, pero tengo un problema con los tipos de retorno de mis funciones de render , específicamente en mis componentes funcionales.

Siempre he usado JSX.Element como el tipo de retorno, ahora esto ya no funciona si un componente decide no mostrar nada, es decir, devuelve null , ya que null no es un valor válido para JSX.Element . Este fue el comienzo de mi viaje. Busqué en la web y descubrí que debería usar ReactNode en su lugar, que incluye null y algunas otras cosas que pueden suceder.

Sin embargo, al crear un componente funcional, TypeScript se queja del tipo ReactNode . Nuevamente, después de algunas búsquedas, encontré que para los componentes funcionales debería usar ReactElement en su lugar. Sin embargo, si lo hago, el problema de compatibilidad desaparecerá, pero ahora TypeScript nuevamente se queja de que null no es un valor válido.

Para abreviar una larga historia, tengo tres preguntas:

  1. ¿Cuál es la diferencia entre JSX.Element , ReactNode y ReactElement ?
  2. ¿Por qué los métodos de render de los componentes de clase devuelven ReactNode , pero los componentes funcionales devuelven ReactElement ?
  3. ¿Cómo resuelvo esto con respecto a null ?
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

1.) ¿Cuál es la diferencia entre JSX.Element, ReactNode y ReactElement?

ReactElement y JSX.Element son el resultado de invocar React.createElement directamente o a través de la transpilación JSX. Es un objeto con type , props y key . JSX.Element es ReactElement , cuyos props y type tienen type any , por lo que son más o menos iguales.

 const jsx = <div>hello</div> const ele = React.createElement("div", null, "hello");

ReactNode se usa como tipo de retorno para render() en componentes de clase. También es el tipo predeterminado para el atributo de children con PropsWithChildren .

 const Comp: FunctionComponent = props => <div>{props.children}</div> // children?: React.ReactNode

Parece más complicado en las declaraciones de tipo React , pero es equivalente a:

 type ReactNode = {} | null | undefined; // super type `{}` has absorbed *all* other types, which are sub types of `{}` // so it is a very "broad" type (I don't want to say useless...)

Puede asignar casi todo a ReactNode . Por lo general, preferiría tipos más fuertes, pero podría haber algunos casos válidos para usarlo.


2.) ¿Por qué los métodos de representación de los componentes de clase devuelven ReactNode, pero los componentes de función devuelven ReactElement?

tl; dr: es una incompatibilidad de tipo TS actual no relacionada con el núcleo React .

  • Componente de clase TS: devuelve ReactNode con render() , más permisivo que React/JS

  • Componente de función TS: devuelve JSX.Element | null , más restrictivo que React/JS

En principio, render() en los componentes de la clase React/JS admite los mismos tipos de devolución que un componente de función. Con respecto a TS, los diferentes tipos son una inconsistencia de tipos que aún se mantiene debido a razones históricas y la necesidad de compatibilidad con versiones anteriores.

Idealmente, un tipo de retorno válido probablemente se parecería más a esto:

 type ComponentReturnType = ReactElement | Array<ComponentReturnType> | string | number | boolean | null // Note: undefined is invalid

3.) ¿Cómo resuelvo esto con respecto a nulo?

Algunas opciones:
 // Use type inference; inferred return type is `JSX.Element | null` const MyComp1 = ({ condition }: { condition: boolean }) => condition ? <div>Hello</div> : null // Use explicit function return types; Add `null`, if needed const MyComp2 = (): JSX.Element => <div>Hello</div>; const MyComp3 = (): React.ReactElement => <div>Hello</div>; // Option 3 is equivalent to 2 + we don't need to use a global (JSX namespace) // Use built-in `FunctionComponent` or `FC` type const MyComp4: React.FC<MyProps> = () => <div>Hello</div>;

Nota: Evitar React.FC no lo salvará del JSX.Element | null restricción de tipo de retorno JSX.Element | null .

La aplicación Create React eliminó recientemente React.FC de su plantilla, ya que tiene algunas peculiaridades como una definición de tipo {children?: ReactNode} implícita. Por lo tanto, es preferible usar React.FC con moderación.

En casos extremos, puede agregar una aserción de tipo o Fragmentos como solución alternativa:
 const MyCompFragment: FunctionComponent = () => <>"Hello"</> const MyCompCast: FunctionComponent = () => "Hello" as any // alternative to `as any`: `as unknown as JSX.Element | null`
over 4 years ago · Santiago Trujillo Denunciar

0

¿Cuál es la diferencia entre JSX.Element, ReactNode y ReactElement?

Un ReactElement es un objeto con un tipo y accesorios.

 type Key = string | number interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> { type: T; props: P; key: Key | null; }

Un ReactNode es un ReactElement, un ReactFragment, una cadena, un número o una matriz de ReactNodes, o nulo, indefinido o booleano:

 type ReactText = string | number; type ReactChild = ReactElement | ReactText; interface ReactNodeArray extends Array<ReactNode> {} type ReactFragment = {} | ReactNodeArray; type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

JSX.Element es un ReactElement, con el tipo genérico para accesorios y el tipo es cualquiera. Existe, ya que varias bibliotecas pueden implementar JSX a su manera, por lo tanto, JSX es un espacio de nombres global que luego establece la biblioteca, React lo establece así:

 declare global { namespace JSX { interface Element extends React.ReactElement<any, any> { } } }

Por ejemplo:

 <p> // <- ReactElement = JSX.Element <Custom> // <- ReactElement = JSX.Element {true && "test"} // <- ReactNode </Custom> </p>

¿Por qué los métodos de representación de los componentes de clase devuelven ReactNode, pero los componentes de función devuelven ReactElement?

De hecho, devuelven cosas diferentes. Devolución de Component :

 render(): ReactNode;

Y las funciones son "componentes sin estado":

 interface StatelessComponent<P = {}> { (props: P & { children?: ReactNode }, context?: any): ReactElement | null; // ... doesn't matter }

En realidad, esto se debe a razones históricas .

¿Cómo resuelvo esto con respecto a nulo?

Escríbalo como ReactElement | null tal como lo hace react. O deje que Typescript infiera el tipo.

fuente de los tipos

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda