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.
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] ycustom 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-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).
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 generarids
ú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 deAxios
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 deflex
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 RouteruseLocation
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 laURL
, donde finalmente se los mandará al componenteBreadcrumb
por medio del atributolist
; así como elstring
de laURL
actual en el atributopathname
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 deCard
, 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 deCard
, 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 componenteSkeleton
como atributo al componenteImg
. - (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 elpathname
(laURL
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 propiedadpathname
. - (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 textoTypes
/Cards
— Debe salir el textoCards
/Cards/Card
— Debe salir el textoCard
/Cards/Card/abc
— Debe salir el textoError 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 propiedadpathname
en el componenteLink
. - (C) — Validamos que si no tiene datos
type
, entonces debe mostrar el componenteLoading
. - (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 propiedadpathname
en el componenteLink
. - (C)— Utilizamos el mock para renderizar los datos.
- (D) — Validamos que si no tiene la imagen
img
, entonces debe mostrar el componenteLoading
. - (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 componenteLoading
- (H) — Si la constante
moreLoading=false y isFinal=false
, va a cargar el componenteButton
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 componenteLoading
. - (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ónsetData
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 utilizarlocalTypes
- 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 auseEffect
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 enApp
). - (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 utilizarlocalTypes, 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 contemplate
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 utilizarlocalTypes, 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:
En la siguiente entrega vamos a ver MongoDB (Parte I) — Definición, un poco de su arquitectura y base de datos de colecciones con documentos
La entrega pasada vimos React — React Router
Bibliografía y links que te puede interesar…
Iconos e imágenes…