¿Quieres embarcarte en un emocionante viaje a través de React con un toque de aventura al estilo pirata de One Piece? En este artículo, exploraremos cómo crear componentes de React con TypeScript y exploraremos otra parte del océano del desarrollo front-end.
Aprenderemos a definir tipos para nuestros componentes, navegar por propiedades (props) como verdaderos capitanes y desbloquear los secretos de los estados (state). Además, aprovecharemos el poder de los genéricos para crear componentes flexibles y personalizables. ¿Vamos?
React es un framework JavaScript que nos permite crear interfaces de usuario de forma interactiva y reactiva. Se basa en la idea de componentes, que son elementos reutilizables que pueden recibir datos y representar parte de la interfaz.
TypeScript es un superconjunto de Javascript que nos permite definir tipos estáticos , orientación a objetos y facilita la escritura de código fácilmente legible. También nos ayuda a identificar y evitar errores en nuestro código.
Cuando usamos TypeScript con React , obtenemos la ventaja de definir bien los tipos de nuestros componentes. Además, nos beneficiamos del principio de falla rápida, que nos permite detectar errores antes y mejorar la calidad del código.
Para comenzar nuestra aventura y crear un proyecto usando React con TypeScript, podemos usar el comando:
npm create vite@latest my-react-app -- --template react-ts
Esto generará una estructura básica del proyecto, con la configuración necesaria para usar TypeScript. Luego podemos comenzar a crear nuestros componentes dentro de la carpeta src. Esta estructura será nuestro barco, donde viviremos varias aventuras en su interior.
Creemos un componente simple llamado Pirata, que representará un personaje de One Piece.
Para crear un componente usando React con TypeScript, podemos usar dos formas: función o clase. En este ejemplo, usaremos la función. Para ello, creamos un archivo llamado Pirata.tsx dentro de la carpeta src/Components. El código del componente es el siguiente:
type PirataProps = {
nombre: string;
cargo: string;
imagen: string;
};
Para construir este componente definimos un tipo llamado PirataProps, que representará las propiedades que recibirá nuestro componente. En este caso son tres: nombre, cargo e imagen, todos de tipo string.
function Pirata({nombre, cargo, imagen} : PirataProps) {
return (
<div className="pirata">
<img src={imagen} alt={nombre} />
<h3>{nombre}</h3>
<p>{cargo}</p>
</div>
);
}
export default Pirata;
A continuación, creamos una función llamada Pirata, que es una función que recibe un objeto con las propiedades definidas en el tipo PirataProps y devuelve un elemento JSX, que es la sintaxis que usa React para renderizar la interfaz.
Dentro de la función, utilizamos la desestructuración de objetos para obtener las propiedades
de nombre, título e imagen del objeto recibido. A continuación, devolvemos un elemento JSX que contiene un div
con la clase pirata
, una imagen con src
y alt
iguales a las propiedades image y name, respectivamente, un h3
con el nombre del personaje y un p
con su rol en la tripulación.
Finalmente exportamos nuestro componente para poder utilizarlo en otros archivos. Para utilizar el componente, vaya al archivo App.tsx
y aplique el componente Pirate
, enviando las propiedades necesarias. Por ejemplo:
function App() {
return (
<>
<Pirata nombre="Chopper" cargo="Médico" imagen="https://i.pinimg.com/564x/ec/5b/57/ec5b57209323835ff8513238a48811eb.jpg" />
</>
)
}
export default App
Y el resultado en pantalla será el siguiente, después de aplicar un poco de estilo al componente:
En nuestro viaje de construcción de componentes con TypeScript, uno de los desafíos que encontraremos es aplicar la interactividad a través de estados y eventos. ¿Cómo podemos definir tipos para manejar estas funcionalidades de forma segura y precisa?
Afrontemos este desafío en la práctica, creando un componente llamado Recompensa
. Este componente mostrará el valor de recompensa de cada personaje y ofrecerá la posibilidad de aumentar o disminuir ese valor, utilizando tipos de TypeScript para garantizar la integridad de los datos y la confiabilidad de la interactividad.
Para crear el componente Recompensa
, crearemos un archivo llamado Recompensa.tsx
dentro de la carpeta src/Components
. El código del componente es el siguiente:
import { useState } from 'react';
type RecompensaProps = {
valorRecompensa: number;
};
Analicemos el código del componente. Primero, importamos el hook useState, que usaremos para administrar el estado del componente. Luego, definimos un tipo llamado RecompensaProps
, que representará la propiedad que recibirá nuestro componente. En este caso, el valor de la recompensa es el número de tipo.
function Recompensa({ valorRecompensa }: RecompensaProps) {
}
A continuación comenzamos a definir la función del componente Recompensa
. Recibe la propiedad RewardValue
como argumento, desestructurando directamente desde los accesorios. TypeScript nos ayuda a comprender que esperamos estas propiedades según el tipo RewardProps
. Si intentáramos acceder a una propiedad que no existe o tiene un tipo incorrecto, TypeScript nos alertaría durante la fase de desarrollo.
function Recompensa({ valorRecompensa }: RecompensaProps) {
const [recompensa, setRecompensa] = useState(valorRecompensa);
const [nuevoValor, setNuevoValor] = useState('');
}
Dentro de la función, usamos useState para crear dos estados: recompensa
y nuevoValor
. TypeScript nos ayuda a especificar explícitamente los tipos de estos estados, dejando más claro lo que esperamos almacenar en ellos. Por ejemplo, recompensa
es de tipo number
y nuevoValor
es string
. TypeScript nos impide asignar un tipo diferente a estos estados.
const handleChange = (evento: React.ChangeEvent<HTMLInputElement>) => {
const valorDigitado = evento.target.value;
setNuevoValor(valorDigitado);
};
Luego, definimos la función handleChange
que maneja el cambio del valor en la entrada de texto. TypeScript nos da el tipo exacto de evento, que es React.ChangeEvent
y la propiedad value del elemento de entrada.
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setRecompensa(nuevoValorNum);
setNuevoValor('');
};
Además, creamos la función handleSubmit
que maneja el envío de formularios. TypeScript nos permite especificar que estamos manejando un evento de formulario (React.FormEvent) y al mismo tiempo nos ayuda a verificar y convertir correctamente el nuevo valor ingresado por el usuario en un número.
//…
return (
<div className="recompensa">
<h3>Recompensa</h3>
<p>{recompensa.toLocaleString()} berries</p>
<form onSubmit={handleSubmit}>
<input
type="number"
value={nuevoValor}
onChange={handleChange}
placeholder="Nuevo valor"
/>
<button type="submit">Actualizar</button>
</form>
</div>
);
}
export default Recompensa;
Finalmente, devolvemos un elemento JSX que contiene un div
con la clase recompensa
, un h3
con el texto Reward
, un p
con el valor recompensa
formateado con el método toLocaleString
, que agrega separadores de miles y decimales, y un formulario con un campo para ingresar el monto de la recompensa y un botón para enviar el valor desde el campo de escritura. El resultado final del código sería:
import { useState } from 'react';
type RecompensaProps = {
nombre: string;
valorRecompensa: number;
};
function Recompensa({ nombre, valorRecompensa }: RecompensaProps) {
const [recompensa, setRecompensa] = useState(valorRecompensa);
const [nuevoValor, setNuevoValor] = useState('');
const handleChange = (evento: React.ChangeEvent<HTMLInputElement>) => {
const valorDigitado = evento.target.value;
setNuevoValor(valorDigitado);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setRecompensa(nuevoValorNum);
setNuevoValor('');
};
return (
<div className="recompensa">
<h3>Recompensa</h3>
<p>{recompensa.toLocaleString()} berries</p>
<form onSubmit={handleSubmit}>
<input
type="number"
value={nuevoValor}
onChange={handleChange}
placeholder="Nuevo valor"
/>
<button type="submit">Actualizar</button>
</form>
</div>
);
}
export default Recompensa;
La asignación de tipos en el manejo de eventos ayuda a prevenir errores comunes que pueden ocurrir durante el manejo de eventos , como intentos de acceder a propiedades inexistentes o pasar argumentos del tipo incorrecto a los controladores de eventos.
La escritura explícita también hace que el código sea más fácil de entender y mantener, lo que mejora la legibilidad y la documentación. Además, las herramientas de desarrollo que admiten la escritura, como TypeScript, brindan retroalimentación inmediata y detectan errores en el momento de la compilación, lo que acelera el proceso de depuración.
Finalmente en nuestro componente lo exportamos para poder usarlo en otros archivos. Un ejemplo de uso sería colocar dentro de la tarjeta del componente Pirata
:
<Recompensa valorRecompensa={10} />
Y aplicando algunas propiedades de estilización, pudimos lograr el siguiente resultado:
Ahora, mientras continúas tu aventura, te encuentras con un problema intrigante. Debes crear un componente llamado Fruta
, que será responsable de mostrar información sobre una variedad de frutas del mundo de One Piece. Hasta ahora, todo bien. Sin embargo, existe un desafío: no se sabe exactamente qué tipo de fruta se mostrará en cada instancia de componente. ¿Cómo afrontar esta incertidumbre?
Para abordar este problema, recurrimos a una característica poderosa de TypeScript: Generics . Con Generics, podemos crear componentes flexibles que puedan manejar diferentes tipos de datos de forma segura. Echemos un vistazo a la solución creando el componente Fruta
.
Para crear el componente Fruta
, crearemos un archivo llamado Fruta.tsx
dentro de la carpeta src/Components
. El código del componente es el siguiente:
type FrutaTipos = 'Paramecia' | 'Zoan' | 'Logia';
En este pedazo de código, estamos creando un tipo llamado FrutaTipos
que es una unión de tres strings: 'Paramecia', 'Zoan' y 'Logia'. Este tipo se utiliza para representar tipos de frutas especiales en el código.
type FrutaProps<T extends FrutaTipos> = {
nombre: string;
imagen: string;
tipo: T;
};
Aquí, estamos definiendo un tipo genérico FrutaProps
que toma un tipo T como parámetro. Este tipo describe las propiedades que acepta el componente Fruta
. Incluye tres propiedades:
string
que representa el nombre de la fruta.FrutaTipos
. Esto significa que el tipo de fruta debe ser una de las opciones válidas.function Fruta({ nombre, imagen, tipo }: FrutaProps<FrutaTipos>): JSX.Element {
return (
<div className="fruta">
<img src={imagen} alt="Imagen de la fruta" />
<h3>{nombre}</h3>
<p>{tipo}</p>
</div>
);
}
export default Fruta;
Aquí estamos creando el componente Fruit
que recibe las propiedades definidas en FrutaProps
. Esto garantiza que el componente solo aceptará propiedades con los tipos correctos. El componente Fruta
presenta las propiedades recibidas de la siguiente manera:
<h3>
usando la propiedad de nombre.<p>
usando la propiedad tipo.Resultado del código completo:
type FrutaTipos = 'Paramecia' | 'Zoan' | 'Logia';
type FrutaProps<T extends FrutaTipos> = {
nombre: string;
imagen: string;
tipo: T;
};
function Fruta({ nombre, imagen, tipo }: FrutaProps<FrutaTipos>): JSX.Element {
return (
<div className="fruta">
<img src={imagen} alt="Imagen de la fruta" />
<h3>{nombre}</h3>
<p>{tipo}</p>
</div>
);
}
export default Fruta;
Finalmente exportamos nuestro componente para poder utilizarlo en otros archivos. Para ver el resultado en pantalla, podemos ir a App.tsx
y aplicar el componente, enviando los props apropiados. Por ejemplo:
<Fruta nombre="Gomu Gomu no Mi" tipo="Paramecia" imagem="https://pm1.aminoapps.com/6309/b9d6ca1c72f20877d9ee0c3aa3d2345502c10a64_hq.jpg" />
El resultado en pantalla, después de aplicar estilizaciones, sería:
En este viaje exploramos los mares agitados del desarrollo front-end con React y TypeScript, todo con un toque de inspiración de One Piece. Desde definir tipos de componentes hasta navegar por propiedades de forma experta, desde desbloquear secretos de estado hasta aprovechar el poder de los generics, nuestro equipo de desarrolladores está ahora mejor equipado que nunca.
Así como la banda pirata de Sombrero de Paja enfrenta desafíos y obstáculos en su búsqueda de One Piece, nosotros también enfrentamos desafíos en nuestros proyectos de desarrollo. Pero con las herramientas adecuadas en nuestras manos, podemos superar cualquier tormenta de códigos que la vida nos depare.
Recuerda que crear componentes de React con TypeScript no solo es una buena práctica, sino también una forma de garantizar un código más seguro, legible y mantenible.
imagen 5
Además, ¿sabía que puedes contar con Tech Guide como tu brújula en este viaje? ¡No olvides comprobarlo!
Gracias por embarcarte con nosotros en esta búsqueda de conocimiento. Sigue explorando, sigue codificando y, quién sabe, tal vez tú también encuentres tu tesoro de "One Piece" en el mundo del desarrollo.
¡Hasta la próxima aventura!
Artículo adaptado y traducido por Daysibel Cotiz.
Monica Mazzochi Hillman
Licenciada en Tecnologías Digitales, especialista en Experiencia de Usuario y posgrado en Docencia y Rendimiento en Educación a Distancia con experiencia en soporte técnico TI y tecnologías front-end. Actualmente es Tech Community Manager en Magalu Cloud e instructora en Alura. En su tiempo libre le gusta ver anime y producciones de Marvel, escuchar kpop y post-hardcore, jugar Valorant y TFT.
Cursos de Programación, Front End, Data Science, Innovación y Gestión.
Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana
Paga en moneda local en los siguientes países
Cursos de Programación, Front End, Data Science, Innovación y Gestión.
Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana
Paga en moneda local en los siguientes países
Puedes realizar el pago de tus planes en moneda local en los siguientes países:
País | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Plan Semestral |
487.37
BOB |
66147.94
CLP |
287031.89
COP |
65.90
USD |
258.28
PEN |
1426.05
MXN |
3028.86
UYU |
65.90
USD |
531.47
GTQ |
34866.34
CRC |
4263.62
DOP |
Plan Anual |
738.82
BOB |
100275.87
CLP |
435121.19
COP |
99.90
USD |
391.54
PEN |
2161.80
MXN |
4591.56
UYU |
99.90
USD |
805.68
GTQ |
52855.05
CRC |
6463.37
DOP |
Acceso a todos
los cursos
Estudia las 24 horas,
dónde y cuándo quieras
Nuevos cursos
cada semana