Javascript
React Hooks
React.js
Los componentes funcionales que pasan props son sorprendentes porque son simples, tienen un rendimiento rápido y requieren de poco código, pero intentar mantener todos los componentes encapsulados puede volverse un infierno. Por otro lado, los componentes de clase a menudo son confusos, tanto para los humanos como para la máquinas, y no suelen entregar una experiencia positiva al desarrollador. Los Hooks proveen una forma para usar los métodos del state y del ciclo de vida con muy poco código, ¡entregándole super poderes a tus componentes!
En general, las props son suficiente para crear un componente sorprendente, pero a veces es necesario más. Estos son algunos ejemplos realmente útiles para saber cuándo usar hooks:
A medida que tengas más experiencia, comprenderás mejor cuándo usar Hooks. Si no los necesitas, ¡NO los uses!¡Cuanto menos mejor!
Para usar hooks, PRIMERO DEBEMOS IMPORTARLOS al inicio de nuestro archivo. Por ejemplo si necesitáramos usar un useState, haríamos lo siguiente:
1import React, { useState } from 'react';
Y si quisieramos usar también el useEffect, lo incluiríamos así:
1import React, { useState, useEffect } from 'react';
Ahora aprendamos a utilizarlos :)
useState
:El hook más importante, ¡casi inevitable! El useState te ayuda a inicializar una variable y cambiar su valor con el tiempo sin recurrir a los componentes padres.
1// Nombre de variable nombre del setter valor inicial (cualquier valor) 2const [ superVariable, setSuperVariable ] = useState( null );
Básicamente, superVariable
se inicializa con null
y luego tu podrás restablecer su valor llamando a setSuperVariable
de esta forma:
1// Aquí estamos restableciendo el valor de superVariable = 'hello' cuando el usuario hace clic en un botón 2<button onClick={() => setSuperVariable('hello')}></button>
useState
1import React, { useState } from "react"; 2import ReactDOM from "react-dom"; 3import "./styles.css"; 4 5const Counter = () => { 6 // Inicializar una variable de "count" en 0, la función setCount se utilizará para restablecer el valor de "count" 7 const [count, setCount] = useState(0); 8 return ( 9 <div> 10 <h2>{count} likes</h2> 11 {/* Restablecer "count" a su valor anterior + 1 */} 12 <span onClick={() => setCount(count + 1)}>👍🏽</span> 13 {/* Restablecer "count" a su valor anterior - 1 */} 14 <span onClick={() => setCount(count - 1)}>👎🏽</span> 15 <h3>Like or dislike to increase/decrease</h3> 16 </div> 17 ); 18}; 19 20ReactDOM.render(<Counter />, document.getElementById("root"));
1import React, { useEffect, useState } from "react"; 2 3const Clock = (props) => { 4 const [time, setTime] = useState(new Date().toLocaleTimeString()); 5 6 useEffect(() => { 7 const interval = setInterval(() => { 8 setTime(new Date().toLocaleTimeString()); 9 }, 1000); 10 return () => clearInterval(interval); 11 }, []); 12 13 14 return ( 15 <div> 16 <h1>{time}</h1> 17 </div> 18 ); 19}; 20 21export default Clock;
1import React, { useEffect, useState } from "react"; 2 3const ControlledInputForm = (props) => { 4 // mantiene el valor de la entrada 5 const [currentValue, setValue] = useState(""); 6 return ( 7 <div> 8 <h2>Your name is: {currentValue ? currentValue : "Not defined"}</h2> 9 10 {/* 11 Esta es una entrada controlada porque su valor está sincronizado 12 con la variable indicada currentValue 13 */} 14 <input 15 type="text" 16 onChange={(e) => setValue(e.target.value)} 17 value={currentValue} 18 placeholder="Please type your name" 19 /> 20 </div> 21 ); 22}; 23 24export default ControlledInputForm;
1import React, { useState } from "react"; 2import ReactDOM from "react-dom"; 3import "./styles.css"; 4 5const Modal = () => { 6 {/** 7 * Usando el hook useState, debes prestar atención a 3 elementos: 8 * - opened: una variable que cambiará con el tiempo (puede tener cualquier nombre) 9 * - setOpened: una función que restablece el valor "opened" (debería tener la palabra "set" antes del nombre de variable que escogiste) 10 * - useState: este es el hook, tiene que ser useState y recibe el valor inicial para "opened" 11 */} 12 const [opened, setOpened] = useState(true); 13 14 {/* si es opened === true, muestro el modal, de lo contrario, muestro el botón para abrir el modal */} 15 return opened ? ( 16 <div> 17 <h1>Hello BreatheCode</h1> 18 <button type="button" onClick={() => setOpened(false)}> 19 Close 20 </button> 21 </div> 22 ) : ( 23 <button type="button" onClick={() => setOpened(true)}> 24 Open 25 </button> 26 ); 27}; 28 29ReactDOM.render(<Modal />, document.getElementById("root"));
Expliquemos este hook con un pequeño ejemplo de ventana modal. Aquí está el código en vivo:
Para implementar una "ventana modal" decidimos crear una variable de estado (useState) llamada opened
que es true
si la ventana modal se muestra al usuario.
Si el usuario hace clic en "close", simplemente usamos la función o setter del hook setOpened
para cambiar el valor de opened
a false
.
useEffect
:useEffect es otro hook increíble que usarás si deseas ejecutar algún código después de que el componente se renderice, por ejemplo:
1const MyComponent = () => { 2 useEffect(() => { 3 4 // Lo que sea que codifiques aquí se ejecutará solo después de la primera vez que el componente se renderize 5 6 }, []); // <------ TEN EN CUENTA EL ARRAY VACÍO 7 8 return <div>Some HTML</div>; 9}
☝ Por favor observa el
[]
como el segundo parámetro del useEffect.
1const MyComponent = () => { 2 useEffect(() => { 3 // Esto se ejecutará cada vez que el componente se vuelva a renderizar 4 if(some_condition){ 5 // Esto se ejecutará solo si some_condition es true 6 } 7 }); // <------ ¡TEN EN CUENTA QUE EL ARRAY VACÍO SE HA IDO! 8 9 return <div>Some HTML</div>; 10}
☝ Este useEffect no tiene un array vacío
[]
como segundo parámetro.
1const MyComponent = () => { 2 useEffect(() => { 3 // Esto se ejecutará solo la primera vez que el componente se renderiza 4 return () => { 5 // Esto se ejecutará justo antes de que el componente se desmonte 6 } 7 }, []); // <------ TEN EN CUENTA EL ARRAY VACÍO 8 9 return <div>Some HTML</div>; 10}
useState
y useEffect
Por ejemplo, supongamos que estoy creando una lista de tareas (Todo list) y tengo que cargar la lista de tareas desde una API. Tendré que buscar la información justo después de que el componente se renderice por primera vez:
1const Todos = (props) => { 2 // Inicializa la variable "tasks" como un array vacío y conéctalo a la función setTasks 3 const [ tasks, setTasks ] = useState([]); 4 5 // Ésta función encapsula la lógica de traer la lista de todos de la api 6 // asi como crear una nueva lista si ésta no existe. 7 const fetchList = async () => { 8 const endpoint = "https://playground.4geeks.com/todo/users/demo"; 9 let response = await fetch(endpoint); 10 if (response.ok) { 11 // Sila lista se recibe, las task son cargadas con los todos 12 let data = await response.json(); 13 setTasks(data.todos);// Aquí se actualiza la variable "tasks" con los datos entrantes 14 return response.status; 15 } 16 if (response.status == 404) { 17 // Si la lista no se encuentra, debe ser creada con una petición POST 18 let newList = await fetch(endpoint, { method: "POST" }); 19 if (newList.ok) setTaks([]); 20 } 21 }; 22 23 // Esta función useEffect se ejecutará solo una vez, cuando el componente finalmente se cargue por primera vez 24 useEffect(() => { 25 // here I fetch my todos from the API 26 fetchList(); 27 },[] // <---- thanks to this empty array the use effect will be called only once 28 ); 29 return <ul>{tasks.map((t, index) => <li key={index}>{t.label}</li>)}</ul>; 30} 31
☝ Revisa el código en profundidad y la demostración en vivo haciendo clic aquí.
Para más información, consulte: La documentación oficial de React, también puedes leer cómo crear tus propios hooks.