Estado, Hooks y Props
El estado
El estado de una aplicación se refiere a los datos que se mantienen internamente en la aplicación y que pueden cambiar en respuesta a la interacción del usuario o a otros eventos. En el caso de un botón de “Me gusta”, el estado podría incluir el número de veces que se ha hecho clic en el botón y si el usuario actualmente ha seleccionado o no el botón.
Aquí hay un ejemplo de cómo se podría implementar un botón de “Me gusta” utilizando HTML, CSS y JavaScript:
<button id="likeButton">Like</button>
<p id="likeCount">0 likes</p>
<script>
let likes = 0;
let isLiked = false;
const likeButton = document.querySelector('#likeButton');
const likeCount = document.querySelector('#likeCount');
likeButton.addEventListener('click', () => {
if (!isLiked) {
likes++;
isLiked = true;
likeButton.textContent = 'Unlike';
} else {
likes--;
isLiked = false;
likeButton.textContent = 'Like';
}
likeCount.textContent = `${likes} ${likes === 1 ? 'like' : 'likes'}`;
});
</script>
En este ejemplo, se utiliza JavaScript para mantener el estado del botón de “Me gusta”. Se utiliza una variable likes para mantener el número de veces que se ha hecho clic en el botón y una variable isLiked para mantener si el botón ha sido o no seleccionado. Cuando se hace clic en el botón, se actualizan estas variables y se actualiza el texto del botón y el número de “Me gusta” mostrado en la página.
React aborda el manejo del estado de manera diferente utilizando el concepto de componentes y el estado interno que pueden tener. Aquí está el mismo ejemplo del botón de “Me gusta” implementado en React:
En este ejemplo, se define un componente LikeButton que utiliza el hook useState para mantener el estado interno del botón de “Me gusta”. Se utiliza una variable likes para mantener el número de veces que se ha hecho clic en el botón y una variable isLiked para mantener si el botón ha sido o no seleccionado. Se utiliza la función setLikes para actualizar el valor de likes y la función setIsLiked para actualizar el valor de isLiked.
La función handleLikeClick se utiliza como callback para el evento onClick del botón. Si el botón no ha sido seleccionado (isLiked es false), entonces se incrementa el valor de likes y se establece el estado isLiked en true. Si el botón ya ha sido seleccionado (isLiked es true), entonces se decrementa el valor de likes y se establece el estado isLiked en false.
Hooks
En React, un hook es una función especial que permite a los componentes de React usar características específicas de React, como el estado interno o los efectos secundarios. Los hooks permiten que los componentes de React sean más reutilizables y modulares.
En el ejemplo anterior del botón de “Me gusta”, se utilizó el hook useState para mantener el estado interno del componente. El hook useState es una función que devuelve un array con dos elementos: el estado actual y una función para actualizar el estado. En el ejemplo, el estado actual se llama likes y la función para actualizar el estado se llama setLikes. También se utiliza otro estado interno llamado isLiked y su función para actualizar el estado setIsLiked.
Además de useState, React tiene otros hooks incorporados, como useEffect, useContext y useRef. Aquí hay una breve descripción de algunos de estos hooks:
useEffect: permite que los componentes de React realicen efectos secundarios, como realizar solicitudes de red o actualizar el título de la página.
useContext: permite que los componentes de React accedan a los datos proporcionados por un contexto. Los contextos son una forma de compartir datos entre componentes sin tener que pasar props manualmente a través de todos los niveles de la jerarquía de componentes.
useRef: permite que los componentes de React mantengan una referencia a un elemento DOM específico o a cualquier otro valor mutable. Las referencias son una forma de acceder a un elemento DOM sin tener que buscarlo en el árbol de elementos cada vez que se necesita acceder a él.
Aquí hay un ejemplo de cómo se podría utilizar el hook useEffect en el botón de “Me gusta” para actualizar el título de la página con el número de “Me gusta” actual:
import React, { useState, useEffect } from 'react';
function LikeButton() {
const [likes, setLikes] = useState(0);
const [isLiked, setIsLiked] = useState(false);
const handleLikeClick = () => {
if (!isLiked) {
setLikes(likes + 1);
setIsLiked(true);
} else {
setLikes(likes - 1);
setIsLiked(false);
}
};
useEffect(() => {
document.title = `${likes} ${likes === 1 ? 'like' : 'likes'}`;
}, [likes]);
return (
<div>
<button onClick={handleLikeClick}>
{isLiked ? 'Unlike' : 'Like'} ({likes})
</button>
</div>
);
}
export default LikeButton;
En este ejemplo, se utiliza el hook useEffect para actualizar el título de la página con el número actual de “Me gusta”. El hook useEffect toma una función como argumento que se ejecutará después de que el componente se haya renderizado por primera vez y después de cada actualización posterior. En este ejemplo, la función establece el título de la página utilizando el valor actual de likes. El segundo argumento de useEffect es un array de dependencias, que indica a React cuándo volver a ejecutar la función. En este caso, la función solo se volverá a ejecutar cuando el valor de likes cambie.
Props
En React, las props son objetos que contienen datos que se pasan de un componente padre a un componente hijo. Las props son una forma de comunicación unidireccional entre los componentes. Los componentes padres pueden pasar datos a sus componentes hijos mediante props, y los componentes hijos pueden usar esos datos para renderizar su salida.
En el ejemplo del botón de “Me gusta”, se puede imaginar que este componente es un hijo de otro componente padre que representa una publicación o un artículo en un sitio web. El componente padre podría pasar el número de “Me gusta” actual como una prop al componente hijo. El componente hijo usaría esa prop para mostrar el número de “Me gusta” en su botón.
Aquí hay un ejemplo de cómo se podría usar la prop likes en el botón de “Me gusta”:
import React, { useState } from 'react';
function LikeButton(props) {
const [isLiked, setIsLiked] = useState(false);
const handleLikeClick = () => {
setIsLiked(!isLiked);
props.onLikeClick(!isLiked);
};
return (
<div>
<button onClick={handleLikeClick}>
{isLiked ? 'Unlike' : 'Like'} ({props.likes})
</button>
</div>
);
}
export default LikeButton;
En este ejemplo, se ha eliminado el estado interno del número de “Me gusta” y se ha pasado el número de “Me gusta” como una prop llamada likes. La prop likes se usa para mostrar el número de “Me gusta” en el botón.
Además, se ha agregado una nueva prop llamada onLikeClick, que es una función que se ejecutará cuando el usuario haga clic en el botón. La función onLikeClick se llama con el valor inverso de isLiked, lo que significa que si el botón estaba en “Me gusta”, ahora estará en “No me gusta”, y viceversa.
En la jerarquía de componentes, el componente padre podría tener un estado interno que se actualice cada vez que el usuario haga clic en el botón de “Me gusta”. El componente padre podría pasar esa información como una prop a su hijo LikeButton. El hijo podría usar esa información para cambiar su apariencia y comportamiento en consecuencia.
En resumen, las props son una forma de comunicación unidireccional entre los componentes en React. Permiten que los componentes padres pasen datos a sus componentes hijos, lo que les permite renderizar su salida de manera dinámica y personalizada. Las props son una parte fundamental de la arquitectura de React y son una herramienta clave para crear componentes modulares y reutilizables.
import React, { useState } from 'react';
import LikeButton from './LikeButton';
function Post(props) {
const [likes, setLikes] = useState(0);
const handleLikeClick = (isLiked) => {
if (isLiked) {
setLikes(likes + 1);
} else {
setLikes(likes - 1);
}
};
return (
<div>
<h2>{props.title}</h2>
<p>{props.content}</p>
<LikeButton likes={likes} onLikeClick={handleLikeClick} />
</div>
);
}
export default Post;
y el componente hijo ahora sería:
import React, { useState } from 'react';
function LikeButton(props) {
const [isLiked, setIsLiked] = useState(false);
const handleLikeClick = () => {
setIsLiked(!isLiked);
props.onLikeClick(!isLiked);
};
return (
<button onClick={handleLikeClick}>
{props.likes} {isLiked ? 'Me gusta' : 'No me gusta'}
</button>
);
}
export default LikeButton;
En este ejemplo, el componente LikeButton recibe dos props del componente padre Post: likes y onLikeClick. La prop likes se utiliza para mostrar el número actual de “Me gusta” en el botón, mientras que la prop onLikeClick se utiliza para pasar la función handleLikeClick del componente hijo al componente padre, para que este pueda actualizar el estado interno del número de “Me gusta”.
Dentro del componente LikeButton, se utiliza el hook useState para mantener un estado interno isLiked que indica si el botón ha sido presionado o no. Cuando el usuario hace clic en el botón, la función handleLikeClick se ejecuta, actualiza el estado interno isLiked y llama a la función onLikeClick del componente padre, pasándole el valor inverso de isLiked. De esta manera, el componente padre puede actualizar su estado interno del número de “Me gusta” en función del valor que se pasa desde el componente hijo.
Este ejemplo ilustra cómo los componentes hijos como LikeButton pueden recibir props del componente padre, actualizar su estado interno y llamar a funciones del componente padre para actualizar su estado interno. Esto permite crear componentes modularizados y reutilizables que se pueden utilizar en diferentes partes de una aplicación React.