DEV Community

Cover image for #CienDiasConCourseIt: Día 9/100
Javier Rodriguez
Javier Rodriguez

Posted on

#CienDiasConCourseIt: Día 9/100

Eventos y Hook useState

Resumen

Estos temas, es especial hook, hay que masticarlo bien para saber implementarlos. Es por eso que esta vez no hay práctica, pero se compensa con los ejercicios de prueba.
Eventos y hooks son dos temas muy importantes, ya que empezamos a mezclar lo visto en JS con React. Nos dá un amplio abanico de posibilidades.
Para lo que tengo pensado para el portfolio, necesitaré ver ciertos temas que se explicará en los próximos días.

Podrás ver la lista de los 100 días en este enlace.


Eventos

Podemos utilizar eventos en React, como lo hacemos en JavaScript. Hay unas leves diferencias en su forma de escribir en JSX.

Hací podemos declarar funciones y se ejecuten al hacer click en un button (editamos la App.js de la app first-app creado):

function App() {
    function handleClick(){
        console.log("Click");
    }

    return(
        <div>
            <Blog />
            <button onClick={handleClick}>Tocame</button>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Ahore vemos el onchange:

function App() {
    function handleClick(){
        console.log("Click");
    }

    function handleChange(e) {
        console.log(e);
    }

    return(
        <div>
            <Blog />
            <button onClick={handleClick}>Tocame</button>
            <input type="text" onChange={handleChange} />
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Acá no interactuamos con el DOM como antes, por que ahora tenemos el concepto del virtual DOM.
Por lo tanto, para tener información del elemento a manipular, usamos onChange para llamar a una función que va a recibir un argumento automáticamente e sobre todos los eventos ocurridos. Fijate como está declarado en el input! No le escribimos como en JS handleChange(event), simplemente es handleChange.

En consola, vamos a poder ver todos los eventos del input. Lo que nos interesa (por lo general), es obtener el valor del input.
Esto lo logramos veremos si escribimos console.log(e.target.value) en la función handleChange. Y aprovechando una actualización de ES6, lo podemos escribir así:

function handleChange(e) {
    const { value } = e.target; // Objeto desestructurado
    console.log(value);
}
Enter fullscreen mode Exit fullscreen mode

Con esto, podemos hacer un MONTON de cosas. Y se puede extender a más cuando veamos estado interno. Primero un pequeño ejercicio práctico.
Si queremos tener el valor de dos inputs e identificar por consola a que input corresponde, podemos hacer algo así:

function App() {
    function handleClick(){
        console.log("Click");
    }

    function handleChange(e) {
        const { value, name } = e.target;
        console.log(name, value); // Nombre y valor del input
    }

    return(
        <div>
            <Blog />
            <button onClick={handleClick}>Tocame</button>
            <div>
                <label>Nombre</label>
                <input type="text" name="name" onChange={handleChange} />
            </div>
            <div>
                <label>Apellido</label>
                <input type="text" name="surname" onChange={handleChange} />
            </div>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Es muy poderoso el destructuring assignment, obtuvimos los valores de value y name del input con poco codeo. Y también reutilizamos código. Estas dos cosas es muy importante tenerlas en cuenta, más aún que estamos en React.
En consola vamos a ver algo así:

name J
name Ja
name Jav
name Javi
surname H
surname Ho
surname Hol
surname Hola
Enter fullscreen mode Exit fullscreen mode

Hook useState

Tenemos algo llamado estado interno de un componente, que es la forma que tenemos para pasar información a través de los componentes. Se divide en 3 etapas:

  • Inicialización: Le decimos que tipo va a ser el estado y su valor inicial.
  • Actualización: Actualizamos el valor.
  • Lectura: Leemos el valor.

Hay dos tipos de estados, cada una corresponde al tipo de componente: Para componentes funcionales, tenemos hook useState. Para componentes de clase, se setea un objeto state y actualizandolo con la función setState.

Ahora, vamos a utilizar nuestro último código hecho para App.js de nuestra app first-app. Vamos a querer compartir información del botón al return. Para esto debemos importar el hook.

import React, {useState} from "react"; // Editamos la primera línea.
Enter fullscreen mode Exit fullscreen mode

Dentro del componente App, inicializamos el estado:

const [message, setMessage] = useState("");
Enter fullscreen mode Exit fullscreen mode

Definimos el hook useState con dos valores. El primer valor se lo conoce como getter, porque va a leer la información del estado. El segundo valor se conoce como setter, porque va a actualizar nuestro estado.
Debemos darle un valor inicial, en nuestro caso es vacío.

Ahora, finalizada la fase de inicialización del estado interno, comenzamos con la fase de lectura y actualización (las fases pueden ser en cualquier orden). Editamos nuestro JSX de App.js para ver el estado interno y la función handleClick para que lo actualice.

return (
        <div>
            <span> El valor del estado es: {message}</span>
            <Blog />
            <button onClick={handleClick}>Tocame</button>
            <div>
                <label>Nombre</label>
                <input type="text" name="name" onChange={handleChange} />
            </div>
            <div>
                <label>Apellido</label>
                <input type="text" name="surname" onChange={handleChange} />
            </div>
        </div>
    );
Enter fullscreen mode Exit fullscreen mode
function handleClick() {
        setMessage("Soy un mensaje padre");
    }
Enter fullscreen mode Exit fullscreen mode

Si guardamos cambios y vemos nuestra app en el navegador, vamos a ver lo que escribimos en el span, con el estado inicial que está vacío. Al dar click en el botón, el estado que le dimos desde la función handleClick, lo mostrará en el span.

Podemos hacer que nuestro estado actualice cada vez que tipeamos dentro del input. Vamos a dejar solo un input para poder verlo bien:

Nuestra función App estaría quedando algo así:

function App() {
    const [message, setMessage] = useState("");

    function handleClick() {
        setMessage("Soy un mensaje padre");
    }

    function handleChange(e) {
        const { value } = e.target;
        setMessage(value);
    }

    return (
        <div>
            <span> El valor del estado es: {message}</span>
            <Blog />
            <button onClick={handleClick}>Tocame</button>
            <div>
                <label>Mensaje</label>
                <input type="text" name="name" onChange={handleChange} />
            </div>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Si quiero hacer un contador con un button, lo puedo hacer usando hooks también. Pero acá hay que tener cuidado con esto:
Vamos a estar usando como valor inicial 0, nuestro getter será counter y setter será setCounter. setCounter guardará el valor siguiente de counter, y eso lo podríamos hacer así: setCounter(counter + 1). Esto no está mal, pero tecnicamente puede fallar debido a que no hay forma de estar seguros de que el valor previo se haya guardado y omitir esta parte está re mal.
Hay una solución y es utilizando las arrow functions y una variable que nos asegurará de que siempre usemos el valor previo: prevCounter. Le podemos poner cualquier nombre, en lugar de prevCounter, pero por conveniencia siempre se pone prevNombreDelGetter. Al utilizar una función anónima, esta toma como valor al último valor del estado (la magia de esta lógica vive dentro de la librería de React). Con esto, nos aseguramos de conservar siempre el valor anterior en el estado.
Para el que estudia electrónica, le recordará a los Flip Flops.

Entonces, la función App quedaría así:

function App() {
    const [message, setMessage] = useState("");
    const [counter, setCounter] = useState(0);

    function handleClick() {
        setMessage("Soy un mensaje padre");
    }

    function handleCounter() {
        setCounter((prevCounter) => prevCounter + 1); // Acá está la magia
    }

    function handleChange(e) {
        const { value } = e.target;
        setMessage(value);
    }

    return (
        <div>
            <span> {counter} </span>
            <button onClick={handleCounter}>+1</button>
            <span> El valor del estado es: {message}</span>
            <Blog />
            <button onClick={handleClick}>Tocame</button>
            <div>
                <label>Mensaje</label>
                <input type="text" name="name" onChange={handleChange} />
            </div>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Día 9/100

Top comments (0)