Todos los componentes que has escrito hasta ahora son funciones: Bienvenida, Cabecera, TarjetaBicicleta, EtiquetaEstado. Es la forma que usarás durante el resto del curso y la que recomienda oficialmente el equipo de React. Pero React tiene más de una década de historia, y durante buena parte de ella la única manera de escribir un componente con memoria propia era usar una clase. Eso significa que en cuanto te incorpores a un proyecto con recorrido —o abras una respuesta de Stack Overflow de 2018, o leas el código de una librería veterana— te encontrarás class TarjetaBicicleta extends React.Component, this.props, render() y bind. Esta lección tiene un objetivo muy concreto y muy práctico: que sepas leer ese código con soltura, entender qué hace cada pieza y traducirlo mentalmente a la sintaxis moderna. No vas a escribir componentes de clase nuevos; vas a dejar de tenerles miedo.

Contenido

  1. Dos sintaxis para la misma idea
  2. Anatomía de un componente de clase: TarjetaBicicleta reescrita
  3. this.props: los datos que llegan de fuera
  4. constructor, this.state y setState
  5. El problema del this y por qué aparece tanto bind
  6. Tabla comparativa completa
  7. Por qué React recomienda funciones desde 2019
  8. Qué siguen aportando las clases hoy
  9. Traducir de clase a función: tabla de equivalencias
  10. Cómo enfrentarte a código heredado en la práctica

  1. Dos sintaxis para la misma idea

Empecemos por lo esencial: para React son lo mismo. Ambas formas producen elementos, ambas se usan como <TarjetaBicicleta />, ambas participan en la reconciliación exactamente igual y ambas pueden convivir en el mismo árbol. Una función puede renderizar una clase y una clase puede renderizar una función sin ningún problema.

La diferencia está en cómo se declaran y cómo acceden a sus capacidades.

// Componente de función: una función que devuelve JSX
function Bienvenida() {
  return <h1>CicloUrbano</h1>;
}
// Componente de clase: una clase con un método render() que devuelve JSX
import { Component } from 'react';

class Bienvenida extends Component {
  render() {
    return <h1>CicloUrbano</h1>;
  }
}

Los dos se usan igual desde fuera:

<Bienvenida />

Quien escribe <Bienvenida /> no sabe —ni necesita saber— cuál de las dos formas hay detrás. Esa es la razón por la que un proyecto puede migrar de clases a funciones componente a componente, sin big bang.

Un apunte de vocabulario: verás las funciones llamadas componentes funcionales, componentes de función o, en documentación antigua, componentes sin estado (stateless functional components). Este último término quedó obsoleto en 2019: desde los hooks, una función puede tener estado perfectamente.

  1. Anatomía de un componente de clase: TarjetaBicicleta reescrita

Vamos a coger la TarjetaBicicleta del catálogo de CicloUrbano y escribirla como clase. Este código es material de lectura, no un modelo a imitar.

// src/componentes/TarjetaBicicleta.jsx  — VERSIÓN DE CLASE (código heredado)
import { Component } from 'react';
import EtiquetaEstado from './EtiquetaEstado.jsx';

class TarjetaBicicleta extends Component {
  render() {
    return (
      <article className="tarjeta-bicicleta tarjeta-bicicleta--urbana">
        <h3>
          Urbana Clásica <EtiquetaEstado />
        </h3>
        <p>Tipo: urbana</p>
        <p>Estación: Plaza Mayor</p>
        <p>
          <strong>2,50 € / hora</strong>
        </p>
      </article>
    );
  }
}

export default TarjetaBicicleta;

Pieza a pieza:

Elemento Qué significa
import { Component } from 'react' Trae la clase base. También se ve como import React from 'react' + extends React.Component
class TarjetaBicicleta extends Component Declara la clase heredando de la base de React, que aporta this.props, this.state y setState
render() Método obligatorio. React lo llama para saber qué pintar. Es el equivalente exacto al cuerpo de la función
return (...) Devuelve el JSX. Las mismas reglas de siempre: raíz única, className, autocierre
export default TarjetaBicicleta Idéntico a la versión de función

La equivalencia mental clave: render() es al componente de clase lo que el cuerpo de la función es al componente de función. Todo lo que había en el return de tu función, en una clase está dentro de render().

Cuidado con un matiz: extends Component es lo que convierte una clase corriente en un componente de React. Sin esa herencia, React no sabe qué hacer con ella y falla al renderizar.

  1. this.props: los datos que llegan de fuera

Las props son los datos que un componente recibe de su padre. Son el tema completo de la próxima lección, Props; aquí solo nos interesa la diferencia de sintaxis de acceso, porque es lo que más despista al leer código antiguo.

En una función, las props llegan como parámetro:

function TarjetaBicicleta(props) {
  return <h3>{props.bicicleta.modelo}</h3>;
}

En una clase, las props están en this.props:

class TarjetaBicicleta extends Component {
  render() {
    return <h3>{this.props.bicicleta.modelo}</h3>;
  }
}

Aquí tienes la versión de clase completa, ya parametrizada con una bicicleta del dominio.js:

// VERSIÓN DE CLASE con props (código heredado)
import { Component } from 'react';

class TarjetaBicicleta extends Component {
  render() {
    // Patrón habitual: extraer las props al principio de render()
    // para no repetir "this.props." en todo el JSX
    const { bicicleta } = this.props;

    return (
      <article className={`tarjeta-bicicleta tarjeta-bicicleta--${bicicleta.tipo}`}>
        <h3>{bicicleta.modelo}</h3>
        <p>Tipo: {bicicleta.tipo}</p>
        <p>Estado: {bicicleta.estado}</p>
        <p>
          <strong>{bicicleta.precioHora.toFixed(2)} € / hora</strong>
        </p>
      </article>
    );
  }
}

export default TarjetaBicicleta;

Ese const { bicicleta } = this.props; en la primera línea de render() es un patrón que verás constantemente en código heredado. No es magia: es destructuring de ES6 aplicado a this.props.

Dos reglas comunes a las dos sintaxis, que conviene subrayar ya:

  • Las props son de solo lectura en ambos casos. Ni props.bicicleta = … ni this.props.bicicleta = … son válidos. React avisa y el flujo unidireccional se rompe.
  • El nombre props es una convención, no una palabra reservada del lenguaje. En una función podrías llamar al parámetro como quisieras; en una clase, en cambio, this.props sí es un nombre fijo que impone la clase base.

  1. constructor, this.state y setState

El estado es la memoria interna de un componente y es el tema de la lección State. Con clases, se maneja con tres piezas.

// PanelReserva como clase (código heredado)
import { Component } from 'react';

class PanelReserva extends Component {
  // 1. El constructor inicializa el estado
  constructor(props) {
    super(props);            // OBLIGATORIO antes de usar this
    this.state = {
      horas: 1
    };
  }

  // 2. Un método que actualiza el estado
  anadirHora() {
    this.setState({ horas: this.state.horas + 1 });
  }

  render() {
    // 3. La lectura del estado es this.state
    return (
      <section className="panel-reserva">
        <p>Horas de alquiler: {this.state.horas}</p>
      </section>
    );
  }
}

export default PanelReserva;

Las tres piezas, en detalle:

  • constructor(props) + super(props). El constructor es el único sitio donde el estado se asigna directamente con this.state = {…}. La llamada a super(props) es obligatoria: sin ella, this no existe todavía y JavaScript lanza un error. Es uno de los fallos clásicos al escribir clases.
  • this.state. Un objeto único que contiene todo el estado del componente. Es una diferencia importante con la sintaxis moderna, donde se declara un trozo de estado independiente por cada dato.
  • this.setState({…}). La única forma válida de actualizar. Nunca this.state.horas = 5: eso muta el objeto sin avisar a React, así que no se dispara ningún render y la pantalla se queda desactualizada. Además setState hace una fusión superficial: el objeto que le pasas se mezcla con el estado existente, y las claves que no mencionas se conservan.
// Si el estado es { horas: 1, tipo: 'urbana' }
this.setState({ horas: 3 });
// El estado queda { horas: 3, tipo: 'urbana' }  ->  'tipo' se conserva solo

Esa fusión automática es una diferencia real de comportamiento con la sintaxis moderna, donde cada actualización reemplaza el valor completo. Tenlo presente al traducir código: es fuente de errores sutiles.

  1. El problema del this y por qué aparece tanto bind

Este es el punto donde las clases se ganaron su mala fama. En JavaScript, el valor de this dentro de un método depende de cómo se llama al método, no de dónde se define. Cuando pasas un método como manejador de evento, se llama «suelto» y pierde su vínculo con la instancia.

// ROTO: al pulsar, this es undefined y revienta con
// "Cannot read properties of undefined (reading 'setState')"
class PanelReserva extends Component {
  constructor(props) {
    super(props);
    this.state = { horas: 1 };
  }

  anadirHora() {
    this.setState({ horas: this.state.horas + 1 });  // <- this no es la instancia
  }

  render() {
    return <button onClick={this.anadirHora}>Añadir hora</button>;
  }
}

Históricamente hubo tres soluciones, y las verás las tres en código real:

// Solución A (la más común en código antiguo): bind en el constructor
constructor(props) {
  super(props);
  this.state = { horas: 1 };
  this.anadirHora = this.anadirHora.bind(this);   // <- la línea reveladora
}
// Solución B: función flecha en el JSX
<button onClick={() => this.anadirHora()}>Añadir hora</button>
// Solución C (la más moderna dentro de las clases): campo de clase con flecha
anadirHora = () => {
  this.setState({ horas: this.state.horas + 1 });
};

Las funciones flecha no tienen this propio: lo toman del ámbito donde se definieron, que aquí es la instancia. Por eso B y C funcionan.

Cuando abras un fichero y veas un constructor con cuatro líneas this.algo = this.algo.bind(this), ya sabes exactamente qué estás mirando: código de clase resolviendo el problema del this. En los componentes de función este problema sencillamente no existe, porque no hay this en ninguna parte. Es una de las mayores simplificaciones que trajo la sintaxis moderna.

  1. Tabla comparativa completa

Aspecto Componente de función Componente de clase
Declaración function X() { … } class X extends Component { render() { … } }
Verbosidad Mínima: para un componente simple, 3 líneas Alta: clase + render() + a menudo constructor
this No existe. Nada que enlazar Central y problemático: exige bind o flechas
Acceso a props Parámetro: props.bicicleta o destructuring en la firma this.props.bicicleta
Acceso al estado Un valor independiente por dato Un único objeto this.state
Actualizar el estado Función actualizadora por dato; reemplaza el valor this.setState; fusiona superficialmente
Efectos secundarios y ciclo de vida Hooks (Módulo 5) Métodos de ciclo de vida (04-03)
Reutilizar lógica Hooks personalizados: composición sencilla HOC y render props: mucha más ceremonia y anidamiento
Rendimiento Equivalente. La diferencia práctica es despreciable; las funciones son algo más ligeras de transpilar y permiten optimizaciones futuras del compilador Equivalente
Tamaño del código Menor: menos texto por la misma funcionalidad Mayor
Documentación oficial Es la única forma que se enseña desde 2023 Aparece en una sección de API heredada
Soporte de la comunidad Todas las librerías modernas asumen funciones Compatible, pero cada vez menos ejemplos nuevos
¿Sigue soportado en React 19? Sí, es la forma recomendada Sí, no está previsto eliminarlo
Cuándo usarlo Siempre en código nuevo Solo al mantener código existente y en límites de error

  1. Por qué React recomienda funciones desde 2019

En febrero de 2019, React 16.8 introdujo los hooks, y con ellos las funciones dejaron de estar limitadas: podían tener estado, ejecutar efectos y acceder al contexto. A partir de ahí, el equipo de React desaconsejó las clases para código nuevo. Los motivos, en orden de importancia:

  1. Reutilizar lógica con estado era muy difícil. Con clases, compartir comportamiento entre componentes obligaba a patrones como los higher-order components o las render props, que producían árboles con cinco o seis capas de envoltorios sin sentido visual (lo que se conocía como wrapper hell). Los hooks personalizados resuelven esto con una simple llamada a función.

  2. La lógica relacionada quedaba desperdigada. En una clase, suscribirse a algo y cancelar la suscripción vivían en métodos de ciclo de vida distintos y alejados entre sí, mientras que un mismo método mezclaba asuntos que no tenían nada que ver. Con hooks, cada preocupación se agrupa en su propio bloque.

  3. El this confundía a las personas y a las máquinas. Además del problema de enlace que has visto, this complica las optimizaciones automáticas: es más difícil analizar estáticamente una clase que una función.

  4. Menos ruido, menos superficie de error. Comparar las dos versiones de TarjetaBicicleta es elocuente: la de clase necesita un import extra, una declaración de clase, un método render y una indentación adicional para decir exactamente lo mismo.

Muy importante: las clases no están obsoletas ni se van a eliminar. El equipo de React ha sido explícito en que no hay planes de retirarlas y que el código antiguo seguirá funcionando. No hay ninguna urgencia por migrar un proyecto que funciona. Lo que sí hay es una recomendación clara: todo lo nuevo, con funciones.

  1. Qué siguen aportando las clases hoy

Una única cosa, y conviene tenerla identificada con precisión:

Los límites de error (error boundaries) solo se pueden escribir con componentes de clase.

Un límite de error es un componente que captura los errores lanzados por sus hijos durante el render y muestra una interfaz alternativa en lugar de dejar que la aplicación entera se quede en blanco. Necesita los métodos static getDerivedStateFromError y componentDidCatch, que no tienen equivalente en forma de hook. Es el tema de la lección Límites de Error, y allí escribirás el único componente de clase «de verdad» del curso.

En la práctica esto no cambia nada de tu forma de trabajar, por dos razones: los límites de error son uno o dos componentes en toda una aplicación, y librerías como react-error-boundary ya los envuelven para que ni siquiera tengas que escribirlos.

Fuera de ese caso, no queda ninguna capacidad exclusiva de las clases. Todo lo demás —estado, efectos, contexto, referencias al DOM, memorización— tiene su equivalente en hooks.

  1. Traducir de clase a función: tabla de equivalencias

Esta tabla es tu diccionario para leer código heredado. No necesitas dominar todavía la columna de la derecha: cada hook se estudia a fondo en el Módulo 5. Úsala como referencia de traducción.

En una clase En una función
class X extends Component function X()
El cuerpo de render() El cuerpo de la función
this.props.bicicleta El parámetro props.bicicleta, o { bicicleta } en la firma
this.state = { horas: 1 } en el constructor useState(1) para el dato horas
this.state.horas La variable horas
this.setState({ horas: 3 }) La función actualizadora de horas
Fusión automática del estado No la hay: cada dato es independiente
constructor para inicializar La inicialización va en la propia llamada a useState
this.anadirHora.bind(this) Nada. El problema desaparece
componentDidMount useEffect con la lista de dependencias vacía
componentDidUpdate useEffect con dependencias
componentWillUnmount La función de limpieza que devuelve useEffect
shouldComponentUpdate React.memo (08-02)
this.miNodo con createRef useRef (05-03)
static contextType useContext (05-04)
HOC o render props para compartir lógica Un hook personalizado (05-06)
static getDerivedStateFromError Sin equivalente: requiere clase

Aquí tienes la traducción completa de PanelReserva, para que veas la reducción de golpe:

// ANTES: clase (código heredado)
import { Component } from 'react';

class PanelReserva extends Component {
  constructor(props) {
    super(props);
    this.state = { horas: 1 };
    this.anadirHora = this.anadirHora.bind(this);
  }

  anadirHora() {
    this.setState({ horas: this.state.horas + 1 });
  }

  render() {
    return (
      <section className="panel-reserva">
        <p>Horas de alquiler: {this.state.horas}</p>
        <button onClick={this.anadirHora}>Añadir hora</button>
      </section>
    );
  }
}

export default PanelReserva;
// DESPUÉS: función con hooks (la forma del resto del curso)
import { useState } from 'react';

function PanelReserva() {
  const [horas, setHoras] = useState(1);

  return (
    <section className="panel-reserva">
      <p>Horas de alquiler: {horas}</p>
      <button onClick={() => setHoras(horas + 1)}>Añadir hora</button>
    </section>
  );
}

export default PanelReserva;

Veinticinco líneas contra doce, sin this, sin constructor y sin bind. Y no hace falta entender todavía cómo funciona useState por dentro para apreciar la diferencia: lo verás en la próxima lección de estado y a fondo en el Módulo 5.

  1. Cómo enfrentarte a código heredado en la práctica

Un guion sensato cuando aterrizas en un proyecto con clases:

flowchart TD
    A[Encuentro un componente de clase] --> B{¿Tengo que cambiarlo?}
    B -- No --> C[Déjalo. Funciona igual de bien]
    B -- Sí --> D{¿El cambio es pequeño?}
    D -- Sí --> E[Hazlo en la propia clase.<br/>No mezcles arreglo y migración]
    D -- No, es una reescritura --> F{¿Hay pruebas que lo cubran?}
    F -- Sí --> G[Migra a función y apóyate en las pruebas]
    F -- No --> H[Escribe primero las pruebas.<br/>Después migra]

Tres consejos de campo:

  • Migrar por migrar no aporta valor. Un componente de clase estable, probado y que nadie toca no es deuda técnica: es código que funciona. Prioriza migrar aquellos donde vayas a trabajar de todos modos.
  • No mezcles migración y cambio funcional en el mismo commit. Si algo se rompe, no sabrás si fue la traducción o la funcionalidad nueva.
  • Cuidado con la fusión de setState. Es la trampa número uno al traducir: un this.setState({ a: 1 }) conserva b sin decirlo, y la versión con hooks separados hay que escribirla teniendo eso en cuenta.

Y respecto a CicloUrbano: el resto del curso se escribe íntegramente con componentes de función. La única excepción será el límite de error de la lección 04-05, donde la clase es obligatoria por diseño de React. La versión de clase de TarjetaBicicleta que has leído aquí se queda como ejercicio de lectura; tu proyecto conserva la versión de función.

Errores Comunes y Consejos

  • Olvidar super(props) en el constructor. El error es Must call a super constructor in derived class before accessing 'this'. Si escribes una clase y no defines constructor propio, no hay problema; si lo defines, super(props) va siempre en la primera línea.
  • Mutar this.state directamente. this.state.horas = 5 no lanza ningún error visible, pero React no se entera y la pantalla no cambia. Siempre this.setState.
  • Leer this.state justo después de setState y esperar el valor nuevo. Las actualizaciones se agrupan y se aplican después; en la línea siguiente todavía verás el valor antiguo. Es el mismo comportamiento que estudiarás con la sintaxis moderna en State.
  • Escribir el render() con nombre distinto. El método tiene que llamarse exactamente render. Un Render() o un renderizar() produce el error Objects are not valid as a React child o directamente una pantalla vacía.
  • Convertir una clase en función copiando el cuerpo de render() y ya. Hay que revisar además el constructor, los métodos auxiliares, los bind y los métodos de ciclo de vida. El render() es solo una parte.
  • Consejo: cuando veas this. en un fichero de React, ya sabes qué tienes delante. Es el marcador infalible de un componente de clase.
  • Consejo: no te aprendas la sintaxis de clase, apréndete la tabla de traducción. El objetivo es leer, no producir.

Ejercicios

Ejercicio 1

Traduce este componente de clase de CicloUrbano a un componente de función. No necesitas hooks: no tiene estado.

import { Component } from 'react';

class TarjetaEstacion extends Component {
  render() {
    const { estacion } = this.props;
    return (
      <article className="tarjeta-estacion">
        <h3>{estacion.nombre}</h3>
        <p>Barrio: {estacion.barrio}</p>
        <p>Plazas: {estacion.plazas}</p>
      </article>
    );
  }
}

export default TarjetaEstacion;

Ejercicio 2

El siguiente componente de clase falla al pulsar el botón con el mensaje Cannot read properties of undefined (reading 'setState'). Explica con precisión por qué ocurre y da dos soluciones distintas dentro de la propia sintaxis de clase.

import { Component } from 'react';

class DisponibilidadEstacion extends Component {
  constructor(props) {
    super(props);
    this.state = { libres: 12 };
  }

  ocuparPlaza() {
    this.setState({ libres: this.state.libres - 1 });
  }

  render() {
    return (
      <section>
        <p>Plazas libres en Plaza Mayor: {this.state.libres}</p>
        <button onClick={this.ocuparPlaza}>Ocupar una plaza</button>
      </section>
    );
  }
}

Ejercicio 3

Un compañero afirma: «Vamos a reescribir los treinta componentes de clase del proyecto a funciones, porque las clases están obsoletas y además rinden peor.» Evalúa las dos afirmaciones técnicas y propón una estrategia razonable. Indica también si hay algún componente que no se pueda migrar.

Soluciones

Solución 1.

// src/componentes/TarjetaEstacion.jsx
function TarjetaEstacion({ estacion }) {
  return (
    <article className="tarjeta-estacion">
      <h3>{estacion.nombre}</h3>
      <p>Barrio: {estacion.barrio}</p>
      <p>Plazas: {estacion.plazas}</p>
    </article>
  );
}

export default TarjetaEstacion;

Los cambios, uno a uno:

Se elimina Se sustituye por
import { Component } from 'react' Nada: una función no necesita nada de React para existir
class … extends Component function TarjetaEstacion(…)
render() { … } El cuerpo de la función
const { estacion } = this.props; El destructuring directamente en la firma: ({ estacion })

De once líneas de ceremonia pasamos a cero. El JSX es idéntico, porque el JSX nunca dependió de la sintaxis del componente.

Solución 2.

Por qué falla. En render(), this.ocuparPlaza no se llama: se pasa como referencia a onClick. Cuando React invoca ese manejador más tarde, lo hace como una función suelta, sin ningún objeto delante del punto. En una clase de JavaScript (que se ejecuta en modo estricto) el this de una función invocada así es undefined, de modo que this.setState intenta leer una propiedad de undefined y lanza el error.

Solución A: enlazar en el constructor.

constructor(props) {
  super(props);
  this.state = { libres: 12 };
  this.ocuparPlaza = this.ocuparPlaza.bind(this);
}

Solución B: declarar el método como campo de clase con función flecha.

ocuparPlaza = () => {
  this.setState({ libres: this.state.libres - 1 });
};

Una tercera opción sería envolver la llamada en el JSX: onClick={() => this.ocuparPlaza()}. Funciona, pero crea una función nueva en cada render, lo cual tiene implicaciones que verás en el Módulo 8.

En un componente de función este problema no puede darse, porque no hay this al que enlazar nada.

Solución 3.

«Las clases están obsoletas»: falso. No están marcadas como obsoletas ni hay planes de eliminarlas. Están desaconsejadas para código nuevo, que es algo distinto: el código existente seguirá funcionando en React 19 y en las versiones siguientes.

«Rinden peor»: falso en la práctica. La diferencia de rendimiento entre ambas sintaxis es despreciable y no será nunca la causa de un problema real. Los cuellos de botella vienen de renders innecesarios, listas enormes o trabajo pesado en el render, no de la forma de declarar el componente. Y esas causas se atacan igual en las dos sintaxis.

Estrategia razonable:

  1. Congelar el crecimiento: todo componente nuevo se escribe como función. Con esto la proporción de código heredado solo puede bajar.
  2. Migración oportunista: cuando haya que tocar un componente de clase por un motivo funcional, se migra en ese momento, en un commit separado del cambio funcional.
  3. Priorizar por dolor real: primero los componentes con bind por todas partes, con lógica duplicada entre componentDidMount y componentDidUpdate, o envueltos en varios HOC. Ahí la migración se paga sola.
  4. Cubrir con pruebas antes de migrar los componentes críticos (Módulo 9).
  5. Nunca migrar «en bloque» sin necesidad. Treinta reescrituras simultáneas son treinta oportunidades de introducir una regresión a cambio de cero valor para el usuario.

Componentes que no se pueden migrar: los límites de error. static getDerivedStateFromError y componentDidCatch no tienen equivalente en hooks, así que esos componentes se quedan como clases (o se delega en una librería que las encapsule). Se estudian en Límites de Error.

Conclusión

Ya sabes leer las dos formas de escribir un componente en React. Un componente de clase extiende Component, obliga a implementar render(), accede a los datos con this.props, guarda su memoria en un único objeto this.state que se actualiza con this.setState —con fusión superficial— y arrastra el problema del this, que explica los bind que pueblan sus constructores. Un componente de función hace lo mismo sin clase, sin render(), sin constructor y sin this, con menos código y con hooks para todo lo que las clases resolvían con métodos de ciclo de vida.

Tienes también el porqué del cambio: los hooks, en 2019, eliminaron la única ventaja que le quedaba a las clases —el estado— y resolvieron mucho mejor el problema de reutilizar lógica. Y tienes la excepción bien delimitada: los límites de error siguen exigiendo una clase, y los verás en 04-05. Fuera de ahí, todo lo demás del curso —y todo lo que escribas en un proyecto moderno— será un componente de función.

Con las dos sintaxis claras, volvemos al techo que dejamos pendiente en la lección anterior: nuestras tres TarjetaBicicleta siguen mostrando la misma bicicleta porque los datos están escritos dentro del componente. En la siguiente lección, Props: Pasando Datos a Componentes, abriremos ese componente al exterior: aprenderás a parametrizarlo, a destructurar sus props en la firma, a darles valores por defecto, a envolver contenido con children y a entender por qué las props son de solo lectura. A partir de ahí, el catálogo de CicloUrbano dejará de ser una maqueta y empezará a mostrar datos de verdad.

Curso de React

Módulo 1: Introducción a React

Módulo 2: Componentes de React

Módulo 3: Trabajando con Eventos

Módulo 4: Conceptos Avanzados de Componentes

Módulo 5: Hooks de React

Módulo 6: Enrutamiento en React

Módulo 7: Gestión del Estado

Módulo 8: Optimización del Rendimiento

Módulo 9: Pruebas en React

Módulo 10: Temas Avanzados

Módulo 11: Proyecto: Construyendo una Aplicación Completa

© Copyright 2026. Todos los derechos reservados