Fundamentos de React

JSX: JavaScript + XML

Imaginemos que estás aprendiendo a escribir en un idioma nuevo que combina palabras de dos idiomas que ya conoces. Esto puede sonar complicado al principio, pero una vez que entiendes cómo se combinan, se convierte en una herramienta poderosa para expresarte de manera más efectiva y eficiente. Esto es un poco lo que sucede con JSX en el mundo de React.

¿Qué es JSX?

JSX significa JavaScript XML. Es una extensión sintáctica para JavaScript que fue diseñada por los creadores de React para facilitar la escritura de la estructura de componentes de la interfaz de usuario. Aunque parece HTML, en realidad es una mezcla de JavaScript y HTML.

¿Por qué usamos JSX en React?

Podrías preguntarte: ¿Por qué no solo usar HTML normal? Bueno, JSX permite expresar la estructura de la interfaz de usuario y la lógica de comportamiento en el mismo lugar. Esto hace que el código sea más legible y, lo más importante, te permite utilizar el poder de JavaScript para definir dinámicamente el contenido de tu UI.

Ejemplos Básicos de JSX

Veamos cómo luce JSX en acción. Aquí tienes un ejemplo simple:

				
					const element = <h1>Hola, mundo!</h1>;

				
			

Aquí, <h1>Hola, mundo!</h1> parece HTML, pero en realidad es JSX. Lo interesante es que puedes integrar expresiones de JavaScript directamente dentro de JSX usando llaves {}:

				
					const name = 'Juan';
const element = <h1>Hola, {name}!</h1>;

				
			

En este ejemplo, el valor de la variable name se inserta dentro del <h1> gracias a las llaves {}. Esto te permite construir dinámicamente elementos de UI basados en datos o lógica de JavaScript.

Cómo JSX se transforma a JavaScript

Es importante saber que JSX no es entendido directamente por los navegadores. Necesita ser transformado a JavaScript convencional antes de que pueda ser ejecutado. Herramientas como Babel son utilizadas en proyectos de React para hacer esta transformación.

Por ejemplo, el código JSX que escribiste antes:

				
					const element = <h1>Hola, {name}!</h1>;

				
			

Babel lo transformará en algo que el navegador puede entender:

				
					const element = React.createElement('h1', null, 'Hola, ', name);

				
			

React.createElement() es una función que toma tres argumentos: el tipo de elemento, sus propiedades o props, y los hijos del elemento, que son los contenidos del elemento.

Reglas Especiales de JSX

Hay unas cuantas reglas especiales que debes recordar al usar JSX:

  • Cerrar Etiquetas: Cada etiqueta en JSX debe cerrarse, ya sea directamente como <img src="url" /> o con una etiqueta de cierre correspondiente como <div></div>.
  • CamelCase para Propiedades: Mientras que en HTML usarías class y onclick, en JSX se utilizan className y onClick para adherirse a la convención de nombres de JavaScript.

Componentes y propiedades (Props)

Adentrémonos en uno de los conceptos más fundamentales y poderosos de React: los componentes y sus propiedades, conocidas como «props». Imagina que estás jugando con bloques de construcción, donde cada bloque puede ser personalizado con pegatinas que determinan cómo se ve o qué hace. En React, esos bloques son los componentes, y las pegatinas son las props.

Componentes en React

Los componentes son las unidades básicas de cualquier aplicación de React. Piensa en ellos como moldes de galletas; puedes usar el mismo molde para hacer muchas galletas del mismo tamaño y forma, pero cada una puede tener diferentes decoraciones o ingredientes. En React, estos moldes son los componentes, y te permiten reutilizar código, mantener tu proyecto organizado y facilitar el manejo del mismo.

Tipos de Componentes

  1. Componentes Funcionales Son la forma más simple de escribir componentes. Se llaman así porque literalmente son funciones de JavaScript. Aquí tienes un ejemplo simple:

				
					function Welcome(props) {
  return <h1>Hola, {props.name}!</h1>;
}

				
			

Componentes de Clase Estos son un poco más elaborados y se definen usando clases de JavaScript. Los componentes de clase pueden contener estado y métodos de ciclo de vida, lo que los hace adecuados para tareas más complejas.

				
					class Welcome extends React.Component {
  render() {
    return <h1>Hola, {this.props.name}!</h1>;
  }
}

				
			

Ambos tipos de componentes pueden aceptar entradas, que son las props.

Props (Propiedades)

Las props son como los parámetros de una función. Son la forma de pasar datos y eventos de un componente padre a un componente hijo. Al igual que puedes darle a alguien una receta de cocina con algunos ingredientes específicos, puedes darle a un componente React algunas props específicas.

Uso de Props

Imagina que quieres saludar a varios usuarios. Puedes crear un componente Welcome y pasar diferentes nombres como props:

				
					function App() {
  return (
    <div>
      <Welcome name="Alice" />
      <Welcome name="Bob" />
      <Welcome name="Carlos" />
    </div>
  );
}

				
			

En este ejemplo, cada <Welcome /> recibe una prop name. Dentro del componente Welcome, accedes a esa prop con props.name (en un componente funcional) o this.props.name (en un componente de clase).

Reglas Importantes sobre Props

  • Lectura Solamente: Nunca debes modificar las props dentro de un componente. Son solo para lectura.
  • Reutilización: Usando diferentes props, puedes reutilizar un componente para mostrar diferentes datos.

Estado y ciclo de vida

Explorar el estado y el ciclo de vida en React es como aprender a cuidar una planta en crecimiento. Al igual que las plantas necesitan agua y nutrientes en diferentes etapas de su vida, los componentes de React tienen «estado» que puede cambiar con el tiempo y «ciclos de vida» que gestionan estos cambios desde su nacimiento hasta que dejan de ser necesarios.

Estado en React

El estado es lo que permite que los componentes de React sean dinámicos y reactivos. Es un objeto que almacena valores que pueden cambiar a lo largo del tiempo, y cada vez que cambia el estado de un componente, el componente se vuelve a renderizar para reflejar esos cambios.

Ejemplo de Estado en un Componente de Clase

Considera un componente que cuenta cuántas veces has hecho clic en un botón. Aquí está cómo podrías implementarlo:

				
					class Counter extends React.Component {
  constructor(props) {
    super(props);
    // Estado inicial
    this.state = { count: 0 };
  }

  handleClick = () => {
    // Actualiza el estado de manera segura
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <button onClick={this.handleClick}>
        Me has clickeado {this.state.count} veces
      </button>
    );
  }
}

				
			

En este ejemplo, this.state.count es una parte del estado del componente. Cuando clickeas el botón, handleClick se llama, actualizando el estado con this.setState, lo que a su vez causa que React vuelva a renderizar el componente para reflejar el nuevo conteo.

Ciclo de Vida de los Componentes

Los componentes en React pasan por varias «fases» durante su existencia, desde que se crean hasta que se eliminan del DOM. React proporciona «métodos del ciclo de vida» que te permiten ejecutar código en momentos específicos de la vida del componente.

Fases del Ciclo de Vida

  1. Montaje

    • constructor(): Se llama antes de que el componente sea montado. Usualmente se inicializa el estado aquí.
    • render(): Se llama para renderizar el componente.
    • componentDidMount(): Se llama después de que el componente se ha montado en el DOM. Es útil para realizar peticiones de datos, establecer temporizadores, etc.
  2. Actualización

    • shouldComponentUpdate(): Permite decidir si React debería continuar con el renderizado.
    • render(): Se llama de nuevo si es necesario.
    • componentDidUpdate(): Se llama después de que la actualización se haya reflejado en el DOM. Buen momento para trabajar con actualizaciones basadas en el DOM anterior.
  3. Desmontaje

    • componentWillUnmount(): Se llama justo antes de que el componente sea eliminado del DOM. Es útil para limpiar cualquier cosa que necesite ser deshecha, como temporizadores o suscripciones.

Ejemplo del Ciclo de Vida en un Componente de Clase

				
					class Timer extends React.Component {
  constructor(props) {
    super(props);
    this.state = { seconds: 0 };
  }

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState(prevState => ({ seconds: prevState.seconds + 1 }));
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return <div>Segundos transcurridos: {this.state.seconds}</div>;
  }
}

				
			

En este ejemplo, componentDidMount se usa para configurar un temporizador, y componentWillUnmount para limpiarlo. Esto asegura que no gastemos recursos innecesariamente y evitamos errores como intentar actualizar el estado de un componente que ya no está montado.