React — Creando una app de Pokémon Trading Card Game con hooks (useState, useEffect y custom Hooks), estilos con react-jss, consumir servicios con Axios y el ruteo con React Router.

Mauricio Garcia
22 min readMar 17, 2021

--

Temario

  • Introducción
  • Creando la app con create-react-app
  • Definiendo las páginas y componentes
  • Revisando la API de Pokémon y sus endpoints
  • Creando los componentes funcionales
  • Creando las Páginas
  • Creando el Provider (Context)
  • Creando los servicios con Axios
  • Construyendo la aplicación para subir a producción
  • Subiendo el proyecto a un servidor (vercel.com)

i. Introducción

Si llegaste aquí directamente y quieres aprender React desde cero, te recomiendo que inicies por acá (React — Primeros pasos…[ref])

En esta entrega vamos a crear una aplicación de las cartas de pokémon[ref] con React, donde haremos:

  • La aplicación con create-react-app[ref]
  • Los estilos con react-jss [ref]
  • Utilizamos los Hooks useState, useEffect[ref] y custom Hooks[ref]
  • Consumiremos los servicios con Axios[ref]
  • Haremos en ruteo con React Router[ref]

…prácticamente… todo lo que hemos aprendido 🤓…

La idea es tener algo así:

Ver proyecto en línea[ref]

ii. Creando la app con create-react-app

Lo primero que vamos a hacer es ir a la carpeta donde tenemos los proyectos, y desde ahí ejecutamos el siguiente comando:

Recuerda que si tienes dudas por que npx, te recomiendo que inicies primero por acá (Mi primera App con create-react-app [ref])

:: Dependencias

Vamos a la carpeta del proyecto, e instalamos:

  • Para los estilos: react-jss

Recuerda que puedes utilizar el que más te guste, revisa esta story para conocer más (React — Formas de diseñar componentes de React, desde estilos en línea hasta CSS in JS[ref])

  • Instalamos react-router-dom[ref][ref], para el ruteo de la aplicación.
  • Instalamos react-image[ref], para la carga de la imagen, este paquete nos da la oportunidad de poner una imagen de “cargando”, y una imagen de “error” (en caso de que no cargue la imagen).
  • Instalamos react-loading-skeleton[ref], este paquete nos va a servir para cargar esqueletos animados, es bastante útil, ya que en vez de mostrar un loading sencillo, podemos poner un cargador más visual (algo así como facebook).
  • Instalamos axios[ref][ref], un cliente HTTP basado en promesas para el navegador y node.js

Si nunca has utilizado axios, date una vuelta por acá (React — Haciendo peticiones con Axios y Hooks [ref])

  • Instalamos uuid[ref], nos va a servir para generar ids únicos.
  • Descargamos las imágenes que vamos a ocupar del siguiente repositorio[ref]; una vez descargadas, vamos a crear una carpeta dentro del proyecto llamada /src/img donde agregaremos las imágenes.
  • Descargamos los archivos mock[ref] que vamos a ocupar ANTES de hacer los servicios del siguiente repositorio[ref]; una vez descargados, vamos a crear una carpeta dentro del proyecto llamada /src/Mocks, donde agregaremos los archivos.

Por último vamos a crear las siguientes carpetas:

  • src/Components — Donde vamos a crear los componentes de la aplicación.
  • src/Pages — Donde vamos a crear las páginas (componentes) de la aplicación.
  • src/Hooks — Donde vamos a crear nuestros hooks personalizados, en el caso de nuestro proyecto servirán para consumir los servicios.
  • src/utils — Donde vamos a crear la configuración de Axios
  • src/Providers — Donde vamos a crear el Contexto global de la aplicación, dicho de otra manera, es donde vamos a almacenar variables globales.

El proyecto debe verse así:

Una vez que se ha descargado todo, vamos a levantar el servidor, y ver la aplicación :

Se debe abrir una ventana en el navegador mostrando la aplicación.

iii. Definiendo las páginas y componentes

El siguiente paso, es definir qué páginas y componentes son los que vamos a construir.

:: Páginas

Vamos a tener 4 páginas:

  • Home — Va a ser la encargada de mostrar los tipos de Pokémon.
  • Cards — Encargada de mostrar las tarjetas de Pokémon que tiene de acuerdo al tipo.
  • Card — Encargada de mostrar a detalle la tarjeta del Pokémon seleccionado.
  • Error404 — Encargada de mostrar un error en la página.

:: Componentes

  • Loading — Va a ser el loading general que se va a mostrar al principio de cada página, y va a ser un svg animado con css[ref]
  • Icon— Encargado de mostrar una imagen de diferentes tamaños (predefinidos), así como agregarle un texto y color.
  • Paragraph — Encargado de mostrar un texto, con la posibilidad de personalizar el color.
  • H1 —Va a representar un texto muy grande, con la posibilidad de agregarle cualquier componente de React al principio.
  • H2 —Va a representar un texto grande, con la posibilidad de agregarle cualquier componente de React al principio.
  • H3 —Va a representar un texto mediano, con la posibilidad de agregarle cualquier componente de React al principio.
  • CustomContainer — Componente con estilos para un contenedor de flex que acepta cualquier componente de React.
  • Button — Encargado de renderizar un botón con estilos predefinidos y nos permite personalizar el color.
  • Breadcrumb — Encargado de mostrar dónde se encuentra se encuentra el usuario, con la finalidad de regresar a alguna de las opciones anteriores.
  • Header — Componente que va a utilizar el hook de React Router useLocation para saber en qué parte de la aplicación se encuentra, la idea es de que genere un arreglo de objetos de cada una de las ramas de la URL, donde finalmente se los mandará al componente Breadcrumb por medio del atributo list; así como el string de la URL actual en el atributo pathname
  • Title— Encargado de mostrar un título principal, al lado un subtítulo y en la parte de abajo un texto, así como también poder agregar del lado izquierdo del título cualquier componente de React.

— Los siguientes componentes son un poco más personalizados, ya que contienen lógica de la aplicación.

  • Boxes — Encargado de mostrar un ícono y un texto del lado derecho.
  • CardDescription — Encargado de mostrar un título, y una lista de textos.
  • CardAttacks — Es un componente para la página de Card, donde nos va a mostrar todos los ataques que tiene la tarjeta (si es que existen datos)
  • CardBoxIcon — Es un componente para la página de Card, donde nos va a mostrar SIEMPRE 4 contenedores, donde mostrará otros detalles.

Nota: Se pueden agregar o quitar componentes, realmente depende de qué tan simple o robusta quieras tu aplicación…

Nota2: Algunos nombres pueden variar (text, name, …), se podrían homologar desde el servicio…

iv. Creando los componentes funcionales

Antes de generar los componentes funcionales, primero, vamos a limpiar el proyecto:

El componente App.js debe quedar así:

Eliminar src/App.css y src/logo.svg

:: Componente Loading

Para este componente, vamos a ir a la pagina loading.io[ref], vamos a copiar el código (CSS y HTML) y lo vamos a convertir en componente, y le agregamos las propiedades de la imagen.

:: Componente Icon

Vamos a crear el componente, con las propiedades que vienen la imagen:

Importamos Img, Skeleton y react-jss:

Construimos el componente:

Donde:

  • (A) — Agregamos una constante con los tamaños predeterminados del icono.
  • (B) — Agregamos el componente Img, con todos los atributos necesarios.
  • (C) — Agregamos el componente SkeletonTheme (para poder agregar color) y el componente Skeleton como atributo al componente Img.
  • (D) — Validamos si viene el texto lo renderizamos, caso contrario null.

Por último agregamos los estilos:

:: Componente Paragraph

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss:

Construimos el componente:

Por último agregamos los estilos:

:: Componente H1

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss:

Construimos el componente:

Por último agregamos los estilos:

:: Componente H2

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss:

Construimos el componente:

Por último agregamos los estilos:

:: Componente H3

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss:

Construimos el componente:

Por último agregamos los estilos:

:: Componente CustomContainer

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss:

Construimos el componente:

Por último agregamos los estilos:

:: Componente Button

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss:

Construimos el componente:

Por último agregamos los estilos:

:: Componente Breadcrumb

Vamos a crear el componente, con las propiedades que vienen la imagen:

Importamos react-jss y react-router-dom:

La idea es tomar la lista, recorrerla y pintar uno a uno:

El siguiente paso es validar si la propiedad pathname coincide con la propiedad name de la lista, en caso de ser cierto renderizamos name, caso contrario renderizamos el componente Link:

Por último agregamos los estilos:

:: Componente Header

La idea es indicarle al usuario en que parte de la aplicación se encuentra, y además, pueda navegar.

Entonces, cuando entramos a la página principal, deberá verse algo así:

Cuando el usuario interactúa con la aplicación, el componente le irá indicando dónde se encuentra.

Vamos a crear el componente:

Importamos react-jss, react-router-dom y Breadcrumb y agregamos los hooks useEffect y useState de react:

Construimos el componente:

Donde:

  • (A) — Vamos a ocupar el hook useLocation para obtener el pathname (la URL actual de la aplicación).
  • (B) — Vamos a ocupar el hook useState (path) para crear un estado , donde guardaremos cada una de las ligas.
  • (C) — Vamos a ocupar el hook useEffect para detectar cuándo cambie la propiedad pathname.
  • (D) — Al tener una URL la idea es separar cada una de ellas y posteriormente agregarla a una lista (url,name).
  • (E) — Actualizamos el estado, con el nuevo arreglo de objetos.
  • (F) — Le mandamos la lista al componente Breadcrumb .

Agregamos los estilos:

:: Componente Title

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss, H1, H2, Paragraph:

Construimos el componente:

Hacemos las validaciones para cada una de las propiedades (title, subtitle, text), en caso de que una propiedad tenga valor, se muestra el contenido, caso contrario no renderiza nada.

Por último agregamos los estilos:

:: Componente Boxes

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss, Icon:

Construimos el componente:

Por último agregamos los estilos:

:: Componente CardDescription

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss, CustomContainer, H2, Paragraph:

Construimos el componente:

En caso de que venga la propiedad type se va a mandar como children al componente H2

Por último agregamos los estilos:

:: Componente Attacks

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss, Boxes, CustomContainer, H2, H3, Paragraph:

Construimos el componente:

Por último agregamos los estilos:

:: Componente CardBoxIcon

Vamos a crear el componente, con las propiedades que vienen la imagen

Importamos react-jss, Boxes, CustomContainer, H3:

Construimos el componente:

Por último agregamos los estilos:

v. Creando el ruteo básico

Una vez que hemos creado todos los componentes, el siguiente paso es crear el ruteo básico, entonces, en el archivo App, vamos a importar react-router-dom y a crear el ruteo básico:

Si levantamos el servidor, debemos de ver lo siguiente:

Si nosotros “navegamos” a través de las siguientes rutas, nos deben de salir las páginas que acabamos de crear:

  • / — Debe salir el texto Types
  • /Cards — Debe salir el texto Cards
  • /Cards/Card — Debe salir el texto Card
  • /Cards/Card/abc — Debe salir el texto Error 404

vi. Creando las páginas

Como aún no hemos creado ningún servicio, vamos a usar de los “mocks” que bajamos previamente.

:: Página principal (Types)

La página Types debe verse de la siguiente manera:

Entonces, en la carpeta src/Pages creamos el componente Types :

Importamos:

  • Paquetes: react-router-dom(Link, useLocation), react-jss(createUseStyles)
  • Componentes: Icon, Loading, Title
  • Imagen: logo.png
  • Mock: Types

Construimos el componente:

Donde:

  • (A) — Utilizamos el mock para renderizar los datos.
  • (B) — Utilizamos el hook useLocation, para utilizar la propiedad pathname en el componente Link.
  • (C) — Validamos que si no tiene datos type, entonces debe mostrar el componente Loading.
  • (D) — Cuando tenemos los datos, lo que hacemos es recorrer uno a uno, con la finalidad de pintar cada uno de los tipos de Pokémon que hay.

Agregamos los estilos:

Vamos al archivo src/App.js, importamos y agregamos el componente Type

Si hemos hecho bien todos los pasos, debemos de ver lo siguiente:

Nota: Por ahora los datos son fijos, entonces, sin importar a qué tipo de Pokémon se le da click, SIEMPRE va a mostrar los mismos datos, cuando hagamos el servicio, se cargarán dinámicamente los datos, así como las imágenes que no se cargan correctamente.

:: Página de Tarjetas (Cards)

La página Cards debe verse de la siguiente manera:

Entonces, en la carpeta src/Pages creamos el componente Cards :

Importamos:

  • Paquetes: react-router-dom(Link, useParams, useLocation, Redirect), react-jss(createUseStyles), react-image(Img), react-loading-skeleton(Skeleton)
  • Componentes: Button, Icon, Loading, Title
  • Mock: Cards

Construimos el componente:

Donde:

  • (A) — Utilizamos el hook useParams, para obtener el tipo de Pokémon (type) de manera dinámica.
  • (B) — Utilizamos el hook useLocation, para utilizar la propiedad pathname en el componente Link.
  • (C)— Utilizamos el mock para renderizar los datos.
  • (D) — Validamos que si no tiene la imagen img, entonces debe mostrar el componente Loading.
  • (E) — Renderizamos el componente Title
  • (F) —Cuando tenemos los datos, lo que hacemos es recorrer uno a uno, con la finalidad de pintar cada una de las tarjetas que tiene.
  • (G) — Si la constante moreLoading=true, va a cargar el componente Loading
  • (H) — Si la constante moreLoading=false y isFinal=false, va a cargar el componente Button

Agregamos los estilos:

Vamos al archivo src/App.js, importamos y agregamos el componente Type

Si hemos hecho bien todos los pasos, debemos de ver lo siguiente:

Nota: Por ahora los datos son fijos, entonces, sin importar a qué tipo de Pokémon se le da click, SIEMPRE va a mostrar los mismos datos, cuando hagamos el servicio, se cargarán dinámicamente los datos, así como las imágenes que no se cargan correctamente.

:: Página principal (Card)

La página Card debe verse de la siguiente manera:

Entonces, en la carpeta src/Pages creamos el componente Card :

Importamos:

  • Paquetes: react-router-dom(useParams, Redirect), react-jss(createUseStyles), react-image(Img), react-loading-skeleton(Skeleton)
  • Componentes: CardDescription, CardAttacks, CardBoxIcon, Loading, Icon, Title
  • Mock: Card

Construimos el componente:

Donde:

  • (A) — Utilizamos el hook useParams, para obtener el id del Pokémon (id) de manera dinámica.
  • (B)— Utilizamos el mock para renderizar los datos.
  • (C) — Obtenemos las propiedades que vamos a utilizar.
  • (D) — Validamos que si no tiene la tarjeta card, entonces debe mostrar el componente Loading.
  • (E)— Si card retorna "Error", redireccionamos a la página de error.
  • (F) — Renderizamos el componente Title
  • (G) — Renderizamos el componente Img.
  • (H) — Renderizamos el detalle de la tarjeta (en caso de que tenga datos)

Agregamos los estilos:

Vamos al archivo src/App.js, importamos y agregamos el componente Type

Si hemos hecho bien todos los pasos, debemos de ver lo siguiente:

Nota: Por ahora los datos son fijos, entonces, sin importar a qué tipo de Pokémon se le da click, SIEMPRE va a mostrar los mismos datos, cuando hagamos el servicio, se cargarán dinámicamente los datos, así como las imágenes que no se cargan correctamente.

:: Página principal (Error404)

La página Error404 debe verse de la siguiente manera:

Entonces, en la carpeta src/Pages creamos el componente Error404 :

Importamos:

  • Paquetes: react-router-dom(useHistory), react-jss(creatUseStyles), Img
  • Componentes: Button
  • Imagen: Snorlax.svg

Construimos el componente:

Donde:

  • (A) — Utilizamos el hook useHistory, para agregar la página a la historia del ruteo.
  • (B) — Cuando se le da click en el botón, lo redireccionamos a la página principal.
  • (C) — Renderizamos el componente.

Agregamos los estilos:

Vamos al archivo src/App.js, importamos y agregamos el componente Type

Si hemos hecho bien todos los pasos, debemos de ver lo siguiente:

Nota: copiar y pegar en el navegador la siguiente URL (http://localhost:3000/Colorless/ex14-91/any) para visualizar la página de Error.

Por último agregamos el componente Header a la App :

Si hemos hecho bien todos los pasos, debemos de ver lo siguiente:

vii. Creando el Provider (Context)

Vamos a crear un Context de React, con la finalidad de almacenar variables globales y poder utilizarlas a lo largo de la aplicación (en el consumo de los servicios).

Dentro de la carpeta src/Providers vamos a crear el archivo GlobalContext, donde agregaremos lo siguiente:

Donde:

  • (A) — Importamos el createContext de React
  • (B) — Creamos un contexto null

Ahora vamos a crear una variable donde vamos a ir almacenando algunos datos que ocuparemos a lo largo de la aplicación, entonces, en la misma carpeta src/Providers, creamos el archivo dataGlobal

Lo primero que vamos a hacer es importar todas las imágenes que tenemos de “tipo de Pokémon”:

Vamos a crear una propiedad llamada localTypes, que es donde vamos a poner el nombre del tipo de pokémon (key), el color bg y la imágen img

Ahora en la App, vamos a importar y agregar el provider GlobalContext:

Vamos a crear un estado de React, para enviar al GlobalContext, donde va a estar inicializado con la variable defaultGlobal

Donde:

  • (A) — Creamos el estado de React, e inicializamos con defaultGlobal
  • (B) — Función que nos va a servir para actualizar los datos del estado.
  • (C) —Se mandan los datos dataGlobal para utilizar los datos y la función setData para actualizar los datos del estado de React.

Si hemos hecho todo bien, ya debemos de ver las imágenes de los tipo de Pokémon:

viii. Creando los servicios con Axios

Para esta aplicación vamos a utilizar la API pokemontcg.io[ref], y los endpoints que vamos a utilizar son los siguientes…

:: Endpoints

  • /types — Este endpoint nos va a servir para obtener la lista de todos los tipos de Pokémon que hay.
  • /cards — Este endpoint nos va a servir para obtener una la lista de tarjetas por tipo de Pokémon.
  • /cards/:id — Este endpoint nos va a servir para obtener todo el detalle de la tarjeta seleccionada.

:: Configurando Axios

Antes de empezar a crear los servicios, primero vamos a crear la instancia; entonces, en la carpeta src/utils vamos a crear el archivo axios.pokemontcg y agregamos lo siguiente:

Donde:

  • (A) — Creamos la instancia con la URL del servicio.
  • (B) — Interceptamos todas las peticiones (esta parte la hice con la finalidad de poder probar todos los servicios en un solo lado, y por si en algún futuro necesita token, solo agregarlo aquí)

Ahora así, vamos a construir los servicios

:: Servicio para Types

En la carpeta src/Hooks creamos el hook llamado useTypes

Importamos:

  • GlobalContext para poder utilizar localTypes
  • La instancia de Axios (pokemonService)
  • De React importamos los hooks useContext, useEffect, useRef

Agregamos constantes que vamos a utilizar:

Donde:

  • (A) — Creamos el estado types para guardar los datos que vengan del servicio.
  • (B) — Importamos dataGlobal
  • (C) — Guardamos la referencia de dataGlobal.localTypes para evitar pasarlo por parámetros a useEffect

Creamos e invocamos el servicio:

Donde:

  • (A) — Tomamos la instancia pokemonService y hacemos la petición.
  • (B) — Cuando el servicio responda correctamente, nos va a regresar una lista de los tipos de Pokémon, la vamos a recorrer y agregar propiedades que necesitamos.
  • (C) — Actualizamos el estado de types .
  • (D) — Retornamos el arreglo.

Ahora vamos al archivo src/Pages/Types y hacemos un pequeño cambio:

Solo debemos importar useTypes, comentar el Mock de TYPES, comentar dónde se utiliza TYPES, y agregar la invocación a useTypes.

El código completo de la página debe verse así:

Si hemos hecho todo bien, debemos de ver los tipos de Pokémon cargando desde el servicio:

Algo que no me gusta de React Router (al menos hasta la versión 5) es la caché de los componentes y servicios, veamos la siguiente animación:

Podemos observar que cada vez que regresamos a la página principal, vuelve a pedir el servicio, lo ideal sería:

  • NO tenemos datos, pedirlos al servicio.
  • SI tenemos datos solo enviarlos.

Entonces, adaptemos el código, el primer paso es ir al archivo /src/Providers/dataGlobal y agregamos una nueva propiedad listType (es donde vamos a guardar los datos)

Vamos al hook useTypes y hacemos los siguientes cambios:

Donde:

  • (A) — Comentamos el estado local types .
  • (B) — Agregamos la función seData (es la que creamos en App).
  • (C) — Agregamos la propiedad que acabamos de crear en dataGlobal .
  • (D) — Hacemos la validación.
  • (E) — Comentamos la actualización del estado local, y mandamos los datos al estado global.
  • (F) — Retornamos la lista.

Expliquemos paso a paso:

  • Cuando entra a la página principal el hook useTypes verifica si tiene datos.
  • En caso de NO tener datos, invoca el servicio y los persiste.
  • En caso de SI tener datos, NO invoca el servicio y regresa los datos persistidos.

:: Servicio para Cards

El primer paso es ir al archivo /src/Providers/dataGlobal y agregamos dos nuevas propiedades cardsByType (es donde vamos a guardar los datos por tipo de Pokémon) y cardsById (es donde vamos a guardar las tarjetas por id)

En la carpeta src/Hooks creamos el hook llamado useCards

Importamos:

  • GlobalContext para poder utilizar localTypes, cardsByType
  • La instancia de Axios (pokemonService)
  • De React importamos los hooks useContext, useEffect, useState, useCallback

Agregamos constantes que vamos a utilizar:

Donde:

  • (A) —Vamos a crear una plantilla de inicio por cada grupo de tarjetas, donde:

id : Nombre del tipo de Pokémon

icon: Es un objeto, donde va a contener el color bg y la imagen img del tipo de Pokémon

cards: Todas las tarjetas que se vayan acumulando,

isFinal: Para saber si se han cargado todas las tarjetas

page: Para saber qué página debemos de mandar a llamar en el servicio

pageSize — Cuantas tarjetas vamos a pedir por servicio

  • (B) — Creamos el estado orderCards que nos va a servir para saber cuándo mandar a llamar el servicio.
  • (C) — Importamos dataGlobal
  • (D) — Obtenemos los datos de dataGlobal.cardsByType[id], en caso de que no tenga inicializamos con template

El siguiente paso es verificar, si es la primera vez que accede (validando page), activamos el servicio:

Creamos e invocamos el servicio:

Donde:

  • (A) —Validamos si podemos pedir el servicio.
  • (B) — Tomamos la instancia pokemonService y hacemos la petición.
  • (C) — Cuando el servicio responda correctamente, cambiamos el estado (para que no vuelva a lanzar el servicio).
  • (D) — Guardamos todas las cartas por id.
  • (E) — Actualizamos los datos de cardsByType y cardsById, persistiendo los datos anteriores con los nuevos.
  • (F) — Creamos la función, para pedir la siguiente página.
  • (G) — Retornamos el arreglo y la función para pedir otra página.

Ahora vamos al archivo src/Pages/Cards y hacemos un pequeño cambio:

Solo debemos importar useCards, comentar el Mock de CARDS, comentar donde se utiliza CARDS, y agregar la invocación a useCards.

El código completo de la Cards debe verse así:

Si hemos hecho todo bien, debemos de ver las tarjetas por tipo de Pokémon:

Expliquemos paso a paso:

  • Cuando entra a la página de ver las tarjetas por tipo de Pokémon, el hook useCards verifica si tiene datos.
  • En caso de NO tener datos, inicializa con una plantilla, invoca al servicio y los persiste.
  • En caso de SI tener datos, NO invoca el servicio y regresa los datos persistidos.
  • Cuando se le da click en el botón de ver más, invoca el servicio y agrega los nuevos registros a los datos persistidos.

:: Servicio para Card

En la carpeta src/Hooks creamos el hook llamado useCard

Importamos:

  • GlobalContext para poder utilizar localTypes, cardsById.
  • La instancia de Axios (pokemonService).
  • De React importamos los hooks useContext, useEffect, useState.

Agregamos constantes que vamos a utilizar:

Donde:

  • (A) — Creamos el estado orderCard que nos va a servir para saber cuándo mandar a llamar el servicio.
  • (B)— Importamos dataGlobal.

El siguiente paso es verificar, si es la primera vez que accede (validando cardsById[id]), activamos el servicio:

Creamos e invocamos el servicio:

Donde:

  • (A) — Validamos si podemos pedir el servicio.
  • (B) — Cambiamos el estado (para que no vuelva a lanzar el servicio).
  • (C)— Tomamos la instancia pokemonService y hacemos la petición.
  • (D) — Actualizamos los datos de cardsById, persistiendo los datos anteriores con los nuevos.
  • (E) — En caso de que ocurra un error, actualizamos los datos.

Antes de enviar los datos, les damos formato, para este caso vamos a crear un archivo en src/utils/cardHelper.jsx y agregamos lo siguiente:

Lo importamos en el hook useCard y lo invocamos:

Por último hacemos cambios en la página de Card :

Si hemos hecho todo bien, debemos de ver el detalle de la tarjeta:

Expliquemos paso a paso:

  • Cuando entra a la página de ver las tarjetas por tipo de Pokémon, el hook useCards verifica si tiene datos.
  • En caso de NO tener datos, inicializa con una plantilla, invoca al servicio y los persiste.
  • En caso de SI tener datos, NO invoca el servicio y regresa los datos persistidos.
  • Cuando entra al detalle de una tarjeta, al tener los datos NO invoca el servicio.
  • Cuando refrescamos la página, al NO tener los datos SI invoca el servicio.

:: Descargar proyecto

Puedes descargar el proyecto de GitHub[ref]

ix. Construyendo la aplicación para subir a producción

Una vez que tenemos el proyecto, el siguiente paso es construir el proyecto para producción, entonces, en consola debemos ejecutar el siguiente comando (no olvides estar en la carpeta del proyecto)

Si lo hemos hecho bien, la consola debe verse algo así:

Con este comando, lo que hace es crear una carpeta dentro de la aplicación, llamada build, que es el proyecto listo para mandar a producción.

x. Subiendo el proyecto a un servidor (vercel.com)

Debemos de tener una cuenta en Github para poder subir el proyecto, si no tienes una cuenta [aquí crea una].

Vamos a crear un nuevo repositorio, dirígete a GitHub y crea un nuevo repositorio[ref] ponle el nombre que creas adecuado para tu repositorio (en mi caso le puse react-pokemon-tcg).

Subimos nuestra aplicación, debe verse algo así:

Ahora el siguiente paso es ir a vercel.com[ref]; si no tienes cuenta solo debes vincular github para tener una[ref].

Una vez vinculada la cuenta, debemos llenar unos datos básicos:

Si hemos hecho todo correctamente, debemos ver una pantalla parecida a esta:

Le damos click a “Import Project”, en la siguiente pantalla le damos al “Continue” de “Import Git Repository”

Copiamos y pegamos la URL de nuestro proyecto git, y le damos en “Continue”:

Las siguientes pantallas son permisos para que Vercel pueda acceder a tu repositorio (lee bien que es lo que más te conviene y dale continuar).

Al final te aparecerá una pantalla como esta:

En esta pantalla puedes configurar variables, o cambiar comandos, para el ejemplo NO vamos a mover nada, solo le damos click a “Deploy

Si hemos hecho bien todos los pasos, debemos de ver una pantalla parecida a esta:

Y eso es todo!, te comparto la liga que he generado:

https://react-pokemon-tcg.vercel.app/

--

--