<Componente />
React.js separa tu código en pequeñas partes llamadas Componentes que pueden crearse / definirse como class o como function. Cada componente es como una aplicación de React más pequeña que tiene su propia lógica y tiene un propósito final que es renderizar algo. (Por ejemplo: un navbar
de bootstrap, una dropdown list - lista desplegable, un modelo, un formulario dinámico, galería de imágenes, formulario de suscripción, casi todo puede diseñarse y codificarse como un componente React). Para hacer eso, el componente de React debe tener un return
que devuelva código JSX (HTML + JS anidado).
1 2import React from 'react'; 3 4// como componente funcional 5function NavBar(props){ 6 return (<nav className="navbar navbar-light bg-light"> 7 <a className="navbar-brand" href="#">Navbar</a> 8 </nav>); 9} 10 11//o como un componente de clase 12import React from 'react'; 13 14class Navbar extends React.Component{ 15 render(){ 16 return (<nav className="navbar navbar-light bg-light"> 17 <a className="navbar-brand" href="#">Navbar</a> 18 </nav>); 19 } 20}
☝️ Este es un componente de clase. Te recomendamos que uses componentes funcionales y hooks en su lugar ya que los componentes de clase están considerados como legacy (deprecados).
Una vez que hayas creado tu componente puedes mostrarlos usando tags de esta forma:
1import React from "react"; 2 3import { render } from "react-dom"; 4 5// aquí le decimos a React que ponga nuestro componente principal <Home /> dentro del elemento DOM con id #myApp 6ReactDOM.render( 7 <Home />, 8 document.querySelector("#myApp") 9); 10 11// o podemos usar el componente Navbar y mostrarlo en la parte superior de nuestro componente Home 12function Home(props){ 13 return ( 14 <div className="container-fluid"> // en JSX debemos usar un atributo llamada 'className en vez de 'class' 15 <Navbar /> 16 <div> 17 ... The rest of Home's contents ... 18 </div> 19 </div> 20 ); 21} 22
A veces un componente necesita información dinámica para mostrar. Por ejemplo, necesitamos nuestro componente <Navbar />
para mostrar la lista de enlaces disponibles y el logo de la marca. Podemos incluir esa información dentro de la llamada del componente <Navbar />
de la misma manera que lo hacemos en los tags HTML.
1 2<Navbar foo="bar" foo2="bar2" /> 3
En este ejemplo, estamos pasando un array de elementos de menú y una URL con el logo al componente NavBar que acabamos de declarar anteriormente.
1let menu = [ 2 {label: 'Home', url: '/home'} 3 {label: 'Contact Us', url: '/contact-us'} 4]; 5<Navbar items={menu} logo="http://path/to/logo.png" />
Ahora, dentro de <Navbar />
podemos usar esos valores (que se entregan a través de la variable Props) para renderizar la información proporcionada.
Y, por último, debemos indicarle a React dónde debe renderizar ese componente en el DOM.
class
Llamamos a los componentes de clase en React stateful porque vienen con un objeto de estado
global (compartido solo dentro del mismo componente) que tiene el único propósito de almacenar los datos necesarios para renderizar el componente. Un uso obvio del objeto state sería, por ejemplo, si tenemos un formulario con campos de entrada que deben ser poblados por el usuario. Los datos ingresados por el usuario deberán ser guardados en algún lugar para poder ser utilizados. El state
será ese lugar.
En otro ejemplo, digamos que estás desarrollando un componente <Clock />
que tiene que imprimir la hora actual cada segundo. Esto significa que nuestro componente tendrá que volver a renderizar cada segundo.
Para que el estado mantenga una página web actualizada, está programado para volver a renderizar el DOM cada vez que se modifica. Entonces, probablemente ya puedas ver cómo puedes aprovechar esta característica: manteniendo tu hora actual dentro del estado y reasignándola con la hora más actual cada segundo. Así:
☝️El siguiente demo actualiza la hora actual cada segundo:
El estado siempre está dentro del método constructor()
de los componentes de clase y se expresa como un literal de objeto JS simple.
Al hablar de modificar el valor del estado, debes recordar que el estado no debe ser mutado directamente. Solo debe modificarse llamando al método especialmente designado this.setState()
. En él, tendrás que pasar un nuevo objeto de estado actualizado que reemplazará los valores de estado anteriores. Por ejemplo:
1 2// una asignación directa de this.state solo está permitida en el método constructor de su clase; en cualquier otro lugar puede causar un error en sus datos almacenados 3constructor(){ 4 super(); 5 this.state = { 6 counter: 0 7 } 8} 9 10// desde cualquier otro lugar de la clase, podemos restablecer el valor de una variable de estado pasando un objeto ACTUALIZADO al método setState() 11const newState = { 12 counter: 2 13}; 14this.setState(newState); 15 16// también puedes hacer la misma operación en línea 17this.setState({ 18 counter: 2 19}); 20// observa cómo arriba hemos pasado la nueva versión completa del estado con {} y el valor del contador actualizado dentro 21// observa que esta nueva versión reemplazará por completo la versión anterior del estado, borrando cualquier otro dato que pueda haber en él
Los cambios de estado ocurren de manera asíncrona y la mutación directa del estado crea una oportunidad para que los valores se actualicen incorrectamente y causen inconsistencias de datos en su aplicación web.
Como se mencionó anteriormente, el lugar para inicializar el estado de su componente es en el método constructor.
El constructor de cada componente se llama automáticamente muy temprano en la ejecución de la aplicación, incluso antes de que su sitio web se haya montado.
Si no necesitas usar el estado, no necesitas implementar explícitamente un método constructor y en algunos ejemplos, verá que este método falta. Sin embargo, si necesitaras usar el estado, es extremadamente importante inicializar tus valores, de lo contrario, en el primer render, tu aplicación devolverá tus variables de estado como undefined.
También necesitarás implementar tu método constructor si usarás alguna propiedad, con el método super(props)
. Eso le permite heredar de la superclase React.Component
de la que todos los componentes de clase React son subclases.
1class ClockComponent extends React.Component { 2 constructor(props){ 3 super(props); 4 // aquí hay un gran lugar para definir el primer valor que tendrá el estado de tu componente 5 this.state = { 6 currentTime: new Date() 7 }; 8 } 9}
Aquí hay una plantilla completa de componente de clase React como referencia:
1 2class Clock extends React.Component { 3 // el método constructor estándar con props y this.state inicializado 4 constructor(props) { 5 super(props); 6 this.state = {date: new Date()}; 7 } 8 9 // un método de ciclo de vida de React 10 componentDidMount() { 11 this.timerID = setInterval( 12 () => this.tick(), 13 1000 14 ); 15 } 16 17 // un método de ciclo de vida de React 18 componentWillUnmount() { 19 clearInterval(this.timerID); 20 } 21 22 // un método personalizado creado por el desarrollador para cumplir un propósito 23 tick() { 24 this.setState({ 25 date: new Date() 26 }); 27 } 28 29 // el método de renderizado estándar con el retorno del componente 30 render() { 31 // aquí se puede insertar cualquier código JS que deba ejecutarse en cada renderizado y se usaría en el retorno a continuación, como variables o declaraciones dinámicas 32 return ( 33 <div> 34 <h1>Hello, world!</h1> 35 <h2>It is {this.state.date.toLocaleTimeString()}.</h2> 36 </div> 37 ); 38 } 39} 40 41ReactDOM.render( 42 <Clock />, 43 document.getElementById('root') 44); 45
☝️ Esto es un componente de clase. Recomendamos encarecidamente que use componentes funcionales y ganchos en su lugar porque los componentes de clase son legado.
componentes
funcionalesLos componentes funcionales son componentes de React simplificados originalmente destinados a fines presentacionales. Por esa razón, tradicionalmente son estáticos: no tienen estado propio. Esto les permite ser más ligeros, más rápidos y más fáciles de escribir.
El estado estático de las funciones fue abordado con React 16.8.0, que introdujo los populares ganchos de React. Desde entonces, el gancho useState
nos permite reproducir el comportamiento de estado en nuestros componentes funcionales:
1 2// elegir un nombre de variable. valor inicial 3// ⬇ ⬇ 4const [ error, setError ] = useState(null); 5// ⬆ 6// elige el nombre del modificador 7 8
Por ejemplo, podemos elegir cualquier variable y modificador como este:
1const [ size, setSize ] = useState(2); 2const [ color, setColor ] = useState("pink"); 3const [ anything, setAnything ] = useState(<any value>);
Entonces, los Hooks de React cambiaron efectivamente la naturaleza de los componentes funcionales originales de React y ahora ambos tipos de componentes son muy similares en las cosas que pueden hacer. Debido a eso, te recomendamos encarecidamente que uses funciones y ganchos tanto como sea posible.
¡Puedes cambiar de un tipo de declaración al otro sin ningún dolor! 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 HTML con lo que este componente debe mostrar cuando se coloca en el sitio web.
Como Clase es más complejo; la declaración de la clase debe heredar de React.Component y contiene muchas más funcionalidades que permiten al desarrollador personalizar la lógica del componente como métodos de ciclo de vida y el estado. Tenga en cuenta que puede crear tantos métodos de clase adicionales como desee.
1// usando funciones 2function MyComponent(){ 3 return Hello; 4} 5// o usando funciones de flecha 6const MyComponent = () => Hello; 7 8// usando clases 9import React from 'react'; 10class MyComponent extends React.Component{ 11 render(){ 12 return Hello; 13 } 14}
Como Función:
Cada variable debe declararse usando el Hook useState dentro de la función
Como Clase:
El estado debe declararse en el constructor y luego usar la función this.setState
para actualizarlo.
1 MyComponent{ 2 constructor(){ 3 super(); 4 this.state = { 5 foo: "var" 6 } 7 } 8 } 9 10jsx 11class MyComponent{ 12 constructor(){ 13 //do something 14 } 15 componentDidMount(){ 16 //do something 17 } 18 render(){ 19 return Hello {this.props.name}; 20 } 21}
Como Función:
Las propiedades se reciben como el primer parámetro de la función de esta manera:
1function MyComponent(props){ 2 return Hello {props.name}; 3}
Como Clase:
Las propiedades están dentro de la variable de clase this.props
, y puedes hacer referencia a ella en cualquier lugar de esta manera:
1class MyComponent{ 2 render(){ 3 return Hello {this.props.name}; 4 } 5}
Como Función:
Usa el gancho useEffect para el ciclo de vida. Más información aquí.
Como Clase:
Tienes todos los métodos disponibles con estos siendo los más importantes: Constructor, ComponentDidMount (o useEffect para Hooks), ComponentWillUnmount (o useEffect para Hooks), etc.
Puedes declarar dentro de tu clase de componente esos métodos y serán llamados mágicamente por React en el momento adecuado, así:
1class MyComponent{ 2 constructor(){ 3 super(); 4 this.state = { //inicializa tu estado } 5 } 6 componentDidMount(){ /* hacer algo al estado aquí */ } 7 componentWillUnmount(){ /* el mejor lugar para eliminar oyentes */ } 8 static getDerivedStateFromProps(nextProps, prevState){ /* devolver el estado actualizado */ } 9 //hay muchos más métodos de ciclo de vida 10 }
🔗 Here you can find more information about all the React JS lifecycle methods.