Un componente de React es una función de JavaScript que devuelve JSX: una pieza reutilizable de UI como un botón, una tarjeta o una página entera. Lo usas como una etiqueta HTML, <Profile />, y React llama a la función para saber qué poner en pantalla. Las apps se construyen poniendo componentes dentro de otros componentes.
App renderiza Profile dos veces, y cada Profile renderiza un Avatar. Cambia las iniciales dentro de Avatar y ambos perfiles se actualizan, porque comparten una sola definición. Por ahora todas las personas de esta lista son iguales; la siguiente página, props, muestra cómo pasarle a cada copia sus propios datos.
Escribir un componente
Un componente de función tiene dos requisitos:
- Su nombre empieza con mayúscula:
Profile, noprofile. - Devuelve algo que React puede renderizar: JSX, una cadena, un número,
null(no renderizar nada) o un array de esas cosas.
function Welcome() {
return <h1>Welcome back</h1>;
}
// Arrow functions work the same way
const Welcome = () => <h1>Welcome back</h1>;
Cuando el JSX ocupa varias líneas, envuélvelo en paréntesis después de return. Sin ellos, un return seguido de un salto de línea devuelve undefined, y todo lo que viene después se ignora.
Por qué el nombre debe ir con mayúscula
JSX mira la primera letra de una etiqueta. Minúscula significa un elemento HTML integrado, así que <div> se queda como <div>. Mayúscula significa "una variable en el ámbito", así que <Profile /> llama a tu función Profile. Si nombras un componente en minúscula, React crea en su lugar un elemento HTML desconocido con ese nombre:
La segunda línea muestra solo su etiqueta, y la consola solo muestra Greeting ran. React puso una etiqueta <greeting> vacía en la página y nunca llamó a la función en minúscula. Un build de desarrollo también advierte que The tag <greeting> is unrecognized in this browser; la vista previa funciona como un build de producción, así que solo ves que falta el texto. Renombra la función a Greetings y la etiqueta a <Greetings /> para arreglarlo.
Componer componentes
Los componentes están hechos para anidarse. Una página es un árbol: App arriba, luego las piezas de diseño, luego partes más pequeñas hasta llegar a botones sueltos. Cada componente solo conoce las piezas que renderiza directamente, así que puedes razonar sobre uno a la vez.
Cada LikeButton tiene su propio estado, así que darle me gusta a una publicación no afecta a las demás. Para agregar un botón de compartir a cada publicación, lo escribes una vez y agregas <ShareButton /> dentro de Post.
Cuándo dividir un componente
No hay una regla fija, pero algunas señales indican que una pieza merece su propio componente: el mismo marcado aparece en dos lugares, una sección del JSX tiene su propio estado (como el botón de me gusta de arriba), o la función creció tanto que tienes que desplazarte para ver su return. Dividir siguiendo esas líneas mantiene cada componente lo bastante pequeño para leerlo en una pantalla. Dividir demasiado pronto cuesta poco: un componente es solo una función, así que volver a unir dos es fácil.
Exportar e importar componentes
Los editores de aquí contienen un solo archivo, pero un proyecto real pone los componentes en sus propios archivos. Un archivo puede tener una exportación por defecto y cualquier número de exportaciones con nombre:
// Avatar.jsx
export default function Avatar({ initials }) {
return <div className="avatar">{initials}</div>;
}
// Badge.jsx
export function Badge({ label }) {
return <span className="badge">{label}</span>;
}
export function NewBadge() {
return <Badge label="new" />;
}
// Profile.jsx
import Avatar from './Avatar.jsx';
import { Badge, NewBadge } from './Badge.jsx';
export default function Profile() {
return (
<div>
<Avatar initials="AL" />
<Badge label="admin" />
<NewBadge />
</div>
);
}
Una exportación por defecto se puede importar con cualquier nombre; una exportación con nombre se importa entre llaves con su nombre exacto. Los equipos suelen elegir un estilo y mantenerlo. Los nombres de archivo suelen coincidir con el componente: Avatar.jsx exporta Avatar.
Mantén los componentes puros
React espera que un componente se comporte como una función pura mientras renderiza: las mismas props y el mismo estado dan el mismo JSX, y renderizar no cambia nada que existiera antes. React puede renderizar un componente muchas veces, en momentos que no controlas, así que un componente que modifica variables externas durante el renderizado produce una salida distinta cada vez.
Las tazas impuras empiezan en 1, 2, 3. Haz clic en el botón: nada de los invitados cambió, y sin embargo la lista impura ahora dice 4, 5, 6, porque cada renderizado sumó a la variable compartida guest. Las tazas puras reciben su número por props y siguen correctas. En desarrollo, Strict Mode renderiza cada componente dos veces para exponer justamente este tipo de error; la vista previa funciona como un build de producción, así que aquí la desviación solo aparece cuando vuelves a renderizar.
Cambiar cosas está bien, solo que no durante el renderizado. Actualiza el estado en los manejadores de eventos, y comunícate con el mundo exterior (temporizadores, suscripciones, el título del documento) en los efectos.
Componentes vs elementos
El componente es la función, Profile. Un elemento es lo que crea JSX cuando escribes <Profile />: un objeto pequeño que dice "renderiza Profile con estas props". React crea elementos, llama a los componentes que nombran y convierte el resultado en DOM. Nunca llamas tú a un componente como Profile(); escribes <Profile /> y dejas que React lo llame, para que pueda seguir su estado y su lugar en el árbol.
Ese lugar importa. Este ejemplo define un componente dentro de otro, un error común:
Escribe algo y luego haz clic en el botón: tu texto desaparece. Cada renderizado de App crea una función NameField completamente nueva, así que React ve un tipo de componente distinto en ese lugar y descarta el anterior junto con su estado. Mueve NameField encima de App, al nivel superior del archivo, y el texto sobrevive a cada clic. La página sobre renderizado explica cómo decide React qué conservar.
Componentes de función y componentes de clase
Antes de que llegaran los hooks en React 16.8, los componentes que necesitaban estado se escribían como clases:
import { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Los componentes de clase siguen funcionando en React 19, y los encontrarás en código antiguo y en los error boundaries, que todavía requieren una clase. El código nuevo usa componentes de función con hooks como useState y useEffect, que hacen el mismo trabajo con menos código. La página de componentes de clase relaciona cada característica de las clases con su hook.
Preguntas frecuentes
¿Qué es un componente en React?
Un componente es una pieza reutilizable de UI escrita como una función de JavaScript que devuelve JSX. Lo usas como una etiqueta HTML, <Profile />, y React llama a la función para saber qué dibujar.
¿Por qué los nombres de los componentes de React deben empezar con mayúscula?
JSX usa la primera letra para decidir qué es una etiqueta. Una etiqueta en minúscula como <profile /> se trata como un elemento HTML llamado profile, y tu función nunca se llama. Una etiqueta con mayúscula como <Profile /> hace referencia a tu componente.
¿Cuál es la diferencia entre componentes de función y de clase?
Ambos describen UI. Los componentes de función son funciones normales y usan hooks para el estado y los efectos; los componentes de clase extienden React.Component y usan métodos como render y componentDidMount. El código nuevo usa componentes de función.
¿Qué es un componente puro en React?
Un componente puro devuelve el mismo JSX para las mismas props y el mismo estado, y no cambia nada fuera de sí mismo mientras renderiza. React depende de esto para renderizar los componentes tantas veces como necesite sin sorpresas.
¿Puedo definir un componente dentro de otro componente?
Evítalo. Un componente definido dentro de otro es una función nueva en cada renderizado, así que React lo trata cada vez como un componente distinto y reinicia su estado. Define los componentes en el nivel superior del archivo.