Imagina que estás construyendo un modelo de una ciudad usando bloques LEGO. Cada edificio, árbol, coche o cualquier otra pieza que puedas colocar en tu modelo de ciudad puede considerarse un componente. En el mundo del desarrollo web, particularmente cuando se utiliza una tecnología llamada React, este concepto es similar.
Un componente React es como una de esas piezas LEGO. Es una unidad autónoma que representa una parte de la interfaz de usuario (UI) en una aplicación web. Al igual que cada bloque LEGO se puede utilizar para construir diferentes partes de tu ciudad modelo y se puede reutilizar en diferentes escenarios, un componente React se puede usar para construir diferentes partes de un sitio web y puede reutilizarse en toda la aplicación.
📝 Los componentes no son un concepto nuevo en el desarrollo web, ya que bibliotecas como bootstrap ya definen los componentes de bootstrap como el
navbar
,lista desplegable
,modal
, etc.
React.js separa tu código en pequeñas piezas llamadas Componentes, que se pueden crear/definir usando una sintaxis de clase (legado) o como una sintaxis de función. Cada componente es como una pequeña aplicación React que tiene su propia lógica y propósito, que es mostrar o renderizar algo de HTML.
Casi cualquier HTML puede ser encapsulado y codificado como un Componente React. Para hacerlo, cada componente React necesita tener una declaración return
que devuelva algún código JSX (HTML + JS embebido). Por ejemplo, aquí está el clásico navbar
de bootstrap encapsulado como un Componente React.
1import React from 'react'; 2 3// un componente de función 4function NavBar(props){ 5 return (<nav className="navbar navbar-light bg-light"> 6 <a className="navbar-brand" href="#">Navbar</a> 7 </nav>); 8}
☝️ Hay una manera antigua de usar clases de js para crear componentes, pero ya no la mostramos ni la recomendamos ya que fue deprecada hace mucho tiempo.
Una vez que has creado tu primer componente, puedes incluirlo o usarlo dentro del resto de tu código escribiendo el nombre de la función como una etiqueta HTML <tag>
. Por ejemplo, si creaste un componente usando la sintaxis de función llamado Home, puedes incluirlo en tu código usando la etiqueta <Home>
de esta manera:
1import React from "react"; 2import ReactDOM from "react-dom"; 3 4// Podemos usar el componente <Navbar /> para mostrarlo en la parte superior del componente Home 5function Home(props){ 6 return ( 7 <div className="container-fluid"> // Observa que en JSX necesitamos usar el nombre de atributo 'className' en lugar de 'class' 8 <Navbar /> 9 <div> 10 ... El resto de los contenidos de Home ... 11 </div> 12 </div> 13 ); 14} 15 16// Aquí le decimos a React que ponga nuestro componente principal de la aplicación <Home /> dentro del elemento DOM con id #myApp 17const root = ReactDOM.createRoot(document.getElementById('myApp')); 18root.render(<Home />); 19
🔥 Observa que en JSX necesitamos usar el nombre de atributo 'className' en lugar de 'class', esto es porque React decidio apegarse al className de los elementos del DOM en lugar de su equivalente class en la sintaxis de HTML.
A veces, un componente necesita información dinámica para mostrar. Por ejemplo, necesitamos que nuestro componente <Navbar />
muestre la lista de enlaces disponibles y el logotipo de la marca. Podemos incluir esa información dentro de la llamada del componente <Navbar />
de la misma manera que lo hacemos en las etiquetas HTML.
1<Navbar foo="bar" foo2="bar2" />
En este ejemplo, estamos pasando un array de elementos de menú y una URL de logotipo al componente NavBar que acabamos de declarar arriba.
1let menu = [ 2 {label: 'Inicio', url: '/home'}, 3 {label: 'Contáctanos', url: '/contact-us'} 4]; 5<Navbar items={menu} logo="http://path/to/logo.png" />
Y, por último, debes decirle a React dónde renderizar ese componente en el DOM.
Llamamos a los componentes en React con estado porque pueden incorporar variables de estado
personalizadas (importando el hook useState) que tienen el único propósito de almacenar los datos necesarios para renderizar el componente correctamente. Un uso obvio del estado sería si, por ejemplo, tenemos un formulario con campos de entrada que necesitan ser llenados por el usuario. Los datos ingresados por el usuario necesitarán ser guardados en algún lugar para poder ser utilizados. Necesitarás una variable de estado
para cada uno de los inputs en el formulario:
1// elige un nombre para la variable valor inicial 2// ⬇ ⬇ 3const [ email, setEmail ] = useState(null); 4// ⬆ 5// elige el nombre del modificador
En otro ejemplo, digamos que estás desarrollando un componente <Clock />
que tiene que imprimir la hora actual cada segundo. Eso significa que nuestro componente necesitará una variable de estado currentDatetime
. Esta variable necesitará ser actualizada cada segundo con la hora actual más nueva, cada vez que la variable se actualice el HTML del componente también se actualizará y mostrará la nueva fecha y hora en la pantalla.
Para que el estado mantenga una página web actualizada, está programado para volver a renderizar el DOM cada vez que se modifica. Así que probablemente ya puedes ver cómo puedes aprovechar esta característica manteniendo tu hora actual dentro del estado y reasignándola a la hora más actual cada segundo. Así:
👇 La siguiente demo actualiza la hora actual cada segundo:
Cuando se habla de modificar el valor del estado, tienes que recordar que el estado no debe ser mutado directamente.
1 2// asumiendo que has declarado un estado "count" así 3// ↓ variable ↓ modificador 4const [ count, setCount ] = useState(0); 5 6# ❌ INCORRECTO: no puedes establecer directamente la variable count = 2 7count = 2 8 9# ✅ CORRECTO: necesitas llamar a la función setCount (el modificador) para actualizar la variable 10setCount(2) 11
🔥 Las variables de estado solo deben ser actualizadas llamando a sus modificadores.
Aquí hay otro ejemplo usando una variable de estado count
y su función modificador llamada setCount
para crear un pequeño componente contador:
1import React, { useState } from 'react'; 2import { createRoot } from 'react-dom/client'; 3 4function Counter() { 5 // useState para mantener y establecer el conteo actual 6 const [count, setCount] = useState(0); 7 8 // Función para incrementar el contador 9 const incrementHandler = () => { 10 setCount(count + 1); 11 }; 12 13 return ( 14 <div> 15 <h1>Conteo: {count}</h1> 16 <button onClick={incrementHandler}>Incrementar</button> 17 </div> 18 19 20 ); 21} 22
Las actualizaciones de estado ocurren de manera asincrónica, y mutar directamente el estado crea una oportunidad para que los valores se actualicen incorrectamente y causen inconsistencias de datos en tu aplicación web.
📝 Lee más sobre el hook de estado de React
El ciclo de vida del componente en React se refiere a la secuencia de fases por las que pasa un componente desde su creación hasta su eliminación del DOM. Este ciclo de vida se puede dividir en tres etapas principales: montaje, actualización y desmontaje.
Montaje: Esta es la fase cuando el componente está siendo creado e insertado en el DOM. Involucra tareas de inicialización y configuración, tales como establecer el estado inicial e integrarse con otros marcos de JavaScript.
Actualización: Esto ocurre cada vez que cambian el estado o las propiedades del componente, desencadenando una nueva renderización del componente. Esta fase puede involucrar la obtención de datos, cálculos y trabajar con el DOM en función de nuevas propiedades o estado.
Desmontaje: Esta fase final ocurre cuando el componente está siendo eliminado del DOM, que es un buen momento para realizar tareas de limpieza como invalidar temporizadores, cancelar solicitudes de red o limpiar suscripciones para evitar fugas de memoria.
useEffect
de React y Ciclo de VidaReact introdujo los hooks en la versión 16.8 para permitir que los componentes funcionales manejen el estado y los efectos secundarios—tareas tradicionalmente manejadas en componentes de clase usando métodos del ciclo de vida como componentDidMount
, componentDidUpdate
y componentWillUnmount
. El hook useEffect
sirve para encapsular la funcionalidad de estos métodos del ciclo de vida en una API, haciendo posible realizar efectos secundarios en componentes funcionales.
Equivalente al componentDidMount
basado en clases: Para replicar el comportamiento de componentDidMount
usando useEffect
, pasas una función y un array de dependencias vacío. Esto le indica a React que ejecute el efecto solo una vez después de la renderización inicial, haciéndolo adecuado para configuraciones como llamadas a API o suscripciones.
1useEffect(() => { 2 // El código aquí se ejecuta solo después de la renderización inicial 3}, []); // Array de dependencias vacío
Equivalente al componentDidUpdate
basado en clases: Incluyendo valores específicos en el array de dependencias, useEffect
volverá a ejecutar el efecto cada vez que esos valores cambien, similar a componentDidUpdate
.
1useEffect(() => { 2 // El código aquí se ejecuta cada vez que 'value' cambia 3}, [value]); // Array de dependencias con 'value'
Equivalente al componentWillUnmount
basado en clases: Para imitar este método del ciclo de vida, useEffect
devuelve una función que será llamada cuando el componente esté a punto de ser desmontado. Esto es ideal para actividades de limpieza.
1useEffect(() => { 2 return () => { 3 // El código de limpieza aquí se ejecuta en el desmontaje del componente 4 }; 5}, []);
El hook useEffect
proporciona una forma unificada y más flexible de manejar efectos secundarios en comparación con los métodos tradicionales del ciclo de vida basados en clases, alineándose con el paradigma de programación funcional y facilitando la reutilización y composición del código. Más sobre el hook useEffect de React
🔗 Aquí puedes encontrar más información sobre todos los métodos del ciclo de vida de React JS.
Los componentes de clase ya no son recomendados, por lo que actualizamos este artículo para eliminar estas explicaciones, por favor utiliza componentes funcionales en su lugar.
A diferencia de los componentes de clase, los componentes funcionales de React son componentes simplificados de React originalmente destinados para propósitos de presentación. Por esa razón, tradicionalmente son sin estado: no tienen estado propio. Eso les
permite ser más ligeros, rápidos y fáciles de escribir.
La falta de estado de las funciones se abordó con React 16.8.0, que introdujo los muy populares React Hooks. Desde entonces, el hook useState
nos permite reproducir el comportamiento del estado en nuestros componentes funcionales:
Así que los React Hooks cambiaron efectivamente la naturaleza de los componentes funcionales de React originales, y ahora ambos tipos de componentes son muy similares en las cosas que pueden hacer. Debido a eso, te alentamos encarecidamente a usar funciones y hooks tanto como sea posible.
¡Puedes cambiar de un tipo de declaración al otro sin ningún problema! Aquí hay una comparación de ambos tipos de componentes:
Como Función: Declaración y uso muy simples. El único propósito de la función es devolver un HTML con lo que el componente se supone que debe mostrar cuando se coloca en el sitio web.
Como Clase: Es más compleja, la declaración de la clase necesita heredar de React.Component y contiene muchas más funcionalidades que permiten al desarrollador personalizar la lógica del componente, como métodos del ciclo de vida y el estado. Por favor, considera que puedes crear tantos métodos de clase adicionales como desees.