Administrar eventos de usuario en React con TypeScript

Juan Diego Rodriguez 11 diciembre 2023
Administrar eventos de usuario en React con TypeScript

Este tutorial mostrará cómo administrar los eventos de los usuarios en React con TypeScript al pasar una función onClick de un componente a otro en las acciones de un usuario.

Administrar eventos de usuario en React con TypeScript

Usaremos create-react-app para iniciar y ejecutar rápidamente un nuevo proyecto React.

npx create-react-app my-app --template typescript
cd my-app
npm run start

Tras instalar los paquetes necesarios e iniciar el servidor de desarrollo, iremos a src/App.tsx, borraremos todo el código repetitivo y dejaremos un componente vacío.

import React from "react";

function Message() {
    return <div></div>;
}

export default Message;

Ahora agregaremos un botón al div en el que el usuario puede hacer clic, y responderemos pasando una función con una alerta dentro del accesorio onClick.

function Message() {
    return (
        <div>
            <button
                onClick={() => {
                    alert("I was clicked!");
                }}>
                Click Me!
            </button>
        </div>
    );
}

Nada cambia de Vanilla React a TypeScript, pero las cosas son diferentes una vez que queremos que la función onClick se pase como accesorio del componente Message. Para mostrar esto, crearemos otro componente llamado Game que tendrá como hijo a Message.

function Game() {
    return (
        <div>
            <Message></Message>
        </div>
    );
}

export default Game;

Y haremos que Message reciba su función onClick y text como accesorios provenientes de Game.

function Message({onClick, text}) {
    return (
        <div>
            <button onClick={onClick}>{text}</button>
        </div>
    );
}

function Game() {
    return (
        <div>
            <Message
                onClick={() => {
                    alert("I was clicked!");
                }}
                text="Click me!"></Message>
        </div>
    );
}

Sin embargo, obtendremos los siguientes errores de compilación si ejecutamos este código.

Binding element 'onClick' implicitly has an 'any' type.
Binding element 'text' implicitly has an 'any' type.

En Vanilla JavaScript, esto no causa un error, pero TypeScript arroja uno ya que los accesorios onClick y text de Message implícitamente tienen un tipo any, es decir, no declaramos qué tipo deberían esos accesorios. Tienda. Debemos crear una interfaz especificando que tipo deben tener los props del Message para solucionar esto.

interface MessageProps {
    text: string;
    onClick: {};
}

El valor que debe tener el accesorio text es fácil de declarar ya que es solo una cadena. Pero el valor de onClick es más difícil.

onClick es más que una función normal ya que tiene una propiedad event, y es una propiedad predeterminada del elemento button. Entonces, para definir onClick, necesitamos una interfaz predefinida que viene con React, que en este caso se llama ButtonHTMLAttributes y contiene todos los tipos de propiedad del elemento button.

Para usarlo, tenemos que extender la interfaz MessageProps para almacenar los tipos ButtonHTMLAttributes.

interface MessageProps extends ButtonHTMLAttributes {
    text: string;
}

Sin embargo, esto no es suficiente, y ejecutar el código de esta manera generará un error ya que la interfaz ButtonHTMLAttributes es un Tipo genérico. Puede pensar en los tipos genéricos como interfaces con variables y, para usarlos, los envolvemos con <> después de declarar la interfaz.

En este caso, la interfaz ButtonHTMLAttributes necesita una variable para saber qué elemento HTML estamos utilizando, y será el HTMLButtonElement global.

interface MessageProps extends ButtonHTMLAttributes<HTMLButtonElement> {
    text: string;
}

MessageProps no solo contiene los tipos de accesorios text y onClick, sino también los tipos de todos los accesorios de un elemento button. Puedes añadir cualquier prop de un button a Message.

En caso de que solo desee extender el accesorio onClick, no extienda la interfaz, cree un nuevo tipo onClick y asigne la propiedad onClick de ButtonHTMLAttributes usando Tipos de acceso indexados.

interface MessageProps {
    text: string;
    onClick: ButtonHTMLAttributes<HTMLButtonElement>["onClick"];
}

Para terminar, debemos declarar que el componente Message utilizará MessageProps para sus props de la siguiente forma.

function Message({onClick, text}: MessageProps) {
    return (
        <div>
            <button onClick={onClick}>{text}</button>
        </div>
    );
}

Y si queremos, podemos anotar el tipo de devolución para que sea un JSX.Element para que TypeScript arroje un error si accidentalmente devolvemos algún otro tipo.

function Message({onClick, text}: MessageProps): JSX.Element {
    return (
        <div>
            <button onClick={onClick}>{text}</button>
        </div>
    );
}

Y este sería el resultado final.

import React from "react";
import {ButtonHTMLAttributes} from "react";

interface MessageProps {
    text: string;
    onClick: ButtonHTMLAttributes<HTMLButtonElement>["onClick"];
}

function Message({onClick, text}: MessageProps): JSX.Element {
    return (
        <div>
            <button onClick={onClick}>{text}</button>
        </div>
    );
}

function Game() {
    return (
        <div>
            <Message
                onClick={() => {
                    alert("I was clicked!");
                }}
                text="Click me!"></Message>
        </div>
    );
}

export default Game;

Ejemplo de código

Juan Diego Rodriguez avatar Juan Diego Rodriguez avatar

Juan Diego Rodríguez (also known as Monknow) is a front-end developer from Venezuela who loves to stay updated with the latest web development trends, making beautiful websites with modern technologies. But also enjoys old-school development and likes building layouts with vanilla HTML and CSS to relax.

LinkedIn