No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Consumiendo la FakeStore API para pintar cards

8/31
Recursos

Aportes 102

Preguntas 14

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

La API de Platzi no es estable y eso puede traerte resultados inesperados como im谩genes sin relaci贸n al producto, poco o demasiados datos, etc. Yo les aconsejo usar la API de Fake Store. Es muy similar.
Para las im谩genes, eliminen 煤nicamente la posici贸n ([0]). En cuanto al t铆tulo de los productos, si les causa ruido que sean muy extensos, pueden agregar la propiedad truncate de Tailwind para agregar elipsis. Tambi茅n puedes agregar un mr-2 (margin-right) y quedar谩 excelente.

Seamos un poco m谩s profesionales 馃槈

Creemos un archivo donde vivir谩 la url de la api en .src/api/index.js:

export const apiUrl = 'https://api.escuelajs.co/api/v1'

Usemos async y await y SIEMPRE usemos try catch en peticiones GET:

import { useState, useEffect } from "react"
import { Layout } from "../../Components/Layout"
import { Card } from "../../Components/Card"

import { apiUrl } from '../../api/'

export const Home = () => {
  const [Items, setItems] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(`${apiUrl}/products`)
        const data = await response.json()
        setItems(data)
      } catch (error) {
        console.error(`Oh no, ocurri贸 un error: ${error}`);
      }
    }
    fetchData()
  }, [])


  return (
    <Layout>
      Home
      <section className="grid gap-4 grid-cols-4 w-full max-w-screen-lg">
        {
          Items?.map(item => (
            <Card
              key={item.id}
              data={item}
            />
          ))
        }
      </section>
    </Layout>
  )
}

Cuando un objeto no existe, React arroja un error y no se renderiza nada. Por ejemplo, si llamamos {data.data.category.name} dentro de un componente y el objeto data, data.category o data.category.name no existen, la pantalla se mostrar谩 en blanco. No obstante, podemos evitar que se rompa la p谩gina si utilizamos la sintaxis opcional de encadenamiento de operadores de navegaci贸n segura, representada por el s铆mbolo ?., de esta forma: {data.data?.category?.name}. En este caso, si alguno de los objetos no existe, la expresi贸n devolver谩 undefined, pero el c贸digo seguir谩 ejecut谩ndose sin problemas. Esto puede resultar muy 煤til si la API no devuelve informaci贸n para algunos productos y queremos evitar que la p谩gina se rompa por completo.

Aplique desestructuraci贸n

{porducts.map((product) => (
 <Card key={product.id} {...product} />
))}

Encontre problemas con FakeApi de Platzi y la cambie por https://fakestoreapi.com/ y asi vamos:

Hice un Loading Skeleton de la Card, dejo el link de la previsualizaci贸n

As铆 voy con Nextjs, creo que est谩 bonito.

Si quieren hacer su propia API con endpoints y todas las configuraciones que deseen, pueden hacerla localmente con json server y hacer el deploy con Render. Es super f谩cil, les dejo un tutorial, est谩 ingles, pero funciona bien:
https://www.youtube.com/watch?v=EcxYcpF3W7c y se adjunta un repo de ejemplo: https://github.com/Md-Irfan-FullStackDeveloper/test_api
Hagan el ejemplo y luego para actualizarla solo tienen que hacer un commit y push a la misma rama, ya que render se conecta con github y en pocos minutos su url se actualiza. Sigan la estructura de la Fake API de Platzi para que no tengan errores de undefined en su c贸digo o si cambian la estructura, no se olviden de adaptar el c贸digo.
En el archivo db.json que creen:

{
  "products": [
  {
    "id": 1,
    "title": "Handmade Fresh Table",
    "price": 687,
    "description": "Andy shoes are designed to keeping in...",
    "category": {
      "id": 5,
      "name": "Others",
      "image": "https://placeimg.com/640/480/any?r=0.591926261873231"
    },
    "images": [
      "https://placeimg.com/640/480/any?r=0.9178516507833767",
      "https://placeimg.com/640/480/any?r=0.9300320592588625",
      "https://placeimg.com/640/480/any?r=0.8807778235430017"
    ]
  },
  {
    "id": 2,
    "title": "Handmade Fresh ",
    "price": 687,
    "description": "Andy shoes",
    "category": {
      "id": 5,
      "name": "Others",
      "image": "https://placeimg.com/640/480/any?r=0.591926261873231"
    },
    "images": [
      "https://placeimg.com/640/480/any?r=0.9178516507833767",
      "https://placeimg.com/640/480/any?r=0.9300320592588625",
      "https://placeimg.com/640/480/any?r=0.8807778235430017"
    ]
  },
  	.
  	. El Resto de Productos
  	.
  ],
  "categories": [
  {
    "id": 1,
    "name": "Clothes",
    "image": "https://api.lorem.space/image/fashion?w=640&h=480&r=4278"
  },
  {
    "id": 2,
    "name": "Electronics",
    "image": "https://api.lorem.space/image/fashion?w=640&h=480&r=4278"
  },
	.
	. El Resto de Categorias
	.
  ]
}

Madre mia, hace al menos un mes que dej茅 el curso por la mitad鈥 Pero desde luego lo que he visto hoy no me parece serio. Le pasa una prop data a card y para recibirla utiliza data.data en vez de desestructurar props en {data} , igualmente si no quiere desestructurarla deberia de llamar a props.data por convenci贸n鈥

Yo me arm茅 un archivo para los endpoints y me hice un hook 鈥榰seFetch鈥

import { useEffect, useState } from 'react';

export const useFetch = apiUrl => {
	const [data, setData] = useState();

	useEffect(() => {
		fetch(apiUrl)
			.then(res => res.json())
			.then(data => setData(data));
	}, [apiUrl]);

	return data;
};

El Home me queda as铆:

import { productsApi } from '../../Assets/ApiUrls';
import { Card } from '../../Components/Card/Card';
import { Layout } from '../../Components/Navbar/Layout/layout';
import { useFetch } from '../../Hooks/UseFetch';

export const Home = () => {
	const data = useFetch(productsApi);

	return (
		<Layout>
			{data?.map(product => (
				<Card key={product?.id} title={product?.title} category={product?.category} price={product.price} image={product.image} />
			))}
		</Layout>
	);
};

En caso de que quieran hacer el grid full responsive usen las siguientes clases de tailwindcss

<section className='grid place-items-center gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 w-full max-w-screen-xl'>
      {items?.map((item) => (
        <Card key={item.id} item={item} />
      ))}
    </section>

Hola comunidad, les comparto mis apuntes en Notion sobre cards y llamado a API麓s, espero les sean de utilidad.
Link aqu铆:
https://bg99astro.notion.site/Cards-y-llamado-a-API-s-b5be45bca26e48a99a25ffb9b650e383

La fakeapi de platzi me esta dando errores, asi que use la api de fake store api, funciona bastante similar a la api de platzi, asi que no hay que hacer muchos cambios.

fake store api

Para los que tambien tienen el error 403 al momento de querer mostrar las imagenes agreguenle la propiedad `referrerpolicy="no-referrer"` a la etiqueta de img en el componente card ![](https://static.platzi.com/media/user_upload/carbon-3f0e437a-3116-4420-9171-310f3a6efbd3.jpg) Probablemente no sea la manera mas adecuada de hacerlo pero es lo unico que me ha servido de momento y al parecer es un tema de imgur. Les dejo el link donde encontre la solucion <https://stackoverflow.com/questions/43895390/imgur-images-returning-403>

mobile-first & lazy-loading

para hacer nuestro home mobile first basta con agregar una linea de c贸digo en tailwind: gid-cols-2, quedar铆a nuestro div de la siguiente manera

grid gap-4  grid-cols-2 sm:grid-cols-4 w-full max-w-screen-lg px-2

ahora para mejorar el rendimiento de nuestra aplicaci贸n deberiamos aplicar el lazy-loading, esto lo logramos de una manera muy sencilla, instalaremos el siguiente paquete
npm i react-lazy-load-image-component

  • luego en nuestra card importamos lo siguiente
import {LazyLoadImage} from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';

y reemplazamos la etiqueta img por la etiqueta LazyLoadImage incluyendo un height, un width y un effect, quedando de la siguiente manera

<LazyLoadImage className='w-full h-full object-cover rounded-lg'
             src={data.data.url} alt={data.data.name} effect='blur' height={'100%'} width={'100%'} />

dentro de los efectos tienes blur, black-and-white y opacity, usa el que desees y no olvides importarlo de css como lo hicimos con blur, de esta manera ya tenemos aplicado el lazy-load en nuestro componente card y hemos mejorado el performance de nuestra aplicaci贸n, as铆 como tambien hemos aplicado la buena tecnica del mobile-first

Debido a que la api tiene images que no funcionan, agregu茅 una validaci贸n para que en caso de que no cargue la imagen, se coloque otra por defecto ```js import { useState } from "react"; import PropTypes from "prop-types"; const Card = ({ data }) => { const [imageError, setImageError] = useState(false); const handleImageError = () => { setImageError(true); }; return (
{data.category?.name}
+

{data.title} ${data.price}

); }; Card.propTypes = { data: PropTypes.object.isRequired, }; export { Card }; ```

Una aclaraci贸n sobre el array que se pasa como segundo argumento (array de dependencias) al useEffect:
Este array le dice a React qu茅 variables debe observar para determinar si el efecto debe ejecutarse nuevamente. Si alguna de las variables dentro del array de dependencias cambia su valor, React ejecutar谩 el efecto nuevamente. Si las variables no cambian, React omitir谩 la ejecuci贸n del efecto.

Algo que no me qued贸 claro es, por qu茅 en el min 18:56 se debe introducir

data.data.category.name 

para obtener el nombre del art铆culo, osea, por qu茅 dos veces data?

Esta es version trabajada con typescript-

Home

import {useState, useEffect} from "react"
import { Layout } from "../../Components/Layout"
import { Card } from "../../Components/Card"

interface MyData {
  id: number;
  title: string;
  price: number;
  description: string;
  category: {
    id: number
    name: string
    image: string
  }
  images: string[]
}

const Home = () => {
  const [items, setItems] = useState<MyData[]>([])

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.escuelajs.co/api/v1/products')
        const data = await response.json()
        setItems(data)
      } catch(error) {
        console.error(error);
      }
    }
    fetchData()
  }, [])
  return (
    <Layout>
      Home
      {items?.map((item) => (
        <Card key={item.id} {...item}/>
      ) )}
      
    </Layout>
  )
}

export {Home}

card

interface MyData {
  id: number;
  title: string;
  price: number;
  description: string;
  category: {
    id: number
    name: string
    image: string
  }
  images: string[]
}


const Card = (data: MyData) => {
  return (
    <div className='bg-white cursor-pointer w-56 h-60 rounded-lg'>
        <figure className='relative mb-2 w-full h-4/5'>
            <span className="absolute bottom-0 left-0 m-2 bg-white/60 rounded-lg text-black text-xs px-3 py-0.5">
              {data.category.name}
            </span>
            <img className="w-full h-full object-cover rounded-lg" 
            src={data.images[0]} alt={data.title} />
            <div className="absolute top-0 right-0 flex justify-center items-center bg-white m-2 w-6 h-6 rounded-full">
                +
                </div>
        </figure>
        <p className="flex justify-between">
            <span className="text-sm font-light">{data.title}</span>
            <span className="text-lg font-medium">${data.price}</span>
        </p>
    </div>
  )
}

export {Card}
Al momento de traer la imagen me da un 403 ![](https://static.platzi.com/media/user_upload/image-6f7d8bbc-da68-410d-8e71-eb7ed3501ba9.jpg)

La API de platzi tiene muchos problemas con las im谩genes. Les recomiendo que hagan el curso usando esta API: https://fakestoreapi.com/

F铆jense en la documentaci贸n de la API para que sepan las cosas que cambian al momento de consumir y renderizar las propiedades del objeto que nos devuelve.

Usando la API de Fake Store debido a problemas con la de Platzi, asi me quedo.

Nose porque no me esta recorriendo el map. solo me muestra un producto.

Vengo despu茅s de 3 meses a hacer de nuevo el proyecto versi贸n dark, mejorando la ux y la ui. Aqui les dejo el avance

No entiendo porque los productos son tan random鈥 aveces inapropiados para presentar este proyecto como parte de mi portafolio. Habra alguna forma de arreglarlo? Una soluci贸n que pienso ahora para mi proyecto es agregar productos a una categoria creada por mi.
. Alguien tiene alguna recomendaci贸n de como solucionar esto?
.
Imagen de categoria electronicos.

.
Detalle de producto

.
Productos agregados al carrito

Que hermoso es TailwindCSS, hay alg煤n curso?

Para que quede un poco m谩s est茅tico pueden usar la destructuracion

const Card = ({ data: { title, price, category, images } }) => {
  
Es mejor deconstruir los props de para que en Card no tengas que hacer data.data, eso se hace f谩cil desde el mismo componentes con `const Card({data}) => {}` Es m谩s natural leerlo as铆
Si no quieres escribir "data.data" para obtener un dato dentro del archivo Card.jsx; deber铆as de recibir la informaci贸n entre llaves: ```js const Card = ({data}) => { ```de esta forma, a la hora de acceder a la informaci贸n solo deber谩s escribir "data" una 煤nica vez
Si no se les cargan las im谩genes prueben usar `localhost:5173` en vez de `127.0.0.1:5173`.

Este curso me tiene muy contento, nunca habia consumido una API tan rapido y entendiendo tanto !!

![](https://static.platzi.com/media/user_upload/image-0cd0cf7f-3ca3-434c-ba6a-819990a9e7bd.jpg) use otra api y no me funciona, el codigo esta igual que la profe

Soy mas apegado a usar async/await en vez de promises. As铆 quedo el useEffect en mi c贸digo.

  useEffect(() => {
    const getProducts = async () => {
      try {
        const data = await fetch('https://api.escuelajs.co/api/v1/products')
        const jsonData = await data.json()
        setItems(jsonData)
      } catch (error) {
        console.log(error)
      }
    }
    getProducts()
  }, [])

Para organizar todo mejor cree un custom hook llamado 鈥渦seFetch鈥. No lo hice yo, lo saqu茅 de https://javascript.plainenglish.io/react-creating-usefetch-custom-hook-d123ebfd5ff.

Adem谩s hice un contexto llamado 鈥淧roductsContext鈥 el cual usa este hook.

Hola, aporto tambi茅n \*\*otra api\*\* que me gusto y es \[dummyJSON]\(https://dummyjson.com/docs/products) es similar a \*\*FakeAPI\*\* la utilice para esta secci贸n. Yo cree una carpeta llamada \*\*helpers\*\* donde realizo el consumo de la api y en el **useEffect** llamo a la funci贸n y luego guardo. Gracias a la comunidad por que tambi茅n me ayudaron a implementarlo leyendo los comentarios. ```js useEffect( () => { getProducts().then( (data) => { setItems(data.products); }); }, []); ``````js //carpeta helpers export const getProducts = async () => { try { const response = await fetch('https://dummyjson.com/products'); const data = await response.json(); return data; } catch (error) { console.error(error); } }; ```

Prefer铆 usar async await y try catch por recomendaci贸n de un compa帽ero, ya que es lo que se recomienda al usar APIs馃槄

Pero tambi茅n me pareci贸 buena idea para practicar y repasar asincronismo en JavaScript
.
Algo que se me ocurri贸 fue hacer un condicional ternario que muestre los productos en funci贸n de si existen o no.
![](

Me qued贸 asi:


si ponene le data dentro de corchetes no deben usar el data.data

const Card = ({data}) => {
 return (
  <div className='bg-white cursor-pointer w-56 h-60 rounded-lg'>
   <figure className='relative mb-2 w-full h-4/5'>
    <span className='absolute bottom-0.5 left-0 bg-white/60 rounded-lg text-black text-xs ml-1 px-1'>{data.category.name}</span>
    <img className='w-full h-full object-cover rounded-lg' src={data.images[0]} alt={data.title} />
    <div className='absolute top-0.5 right-0.5 flex justify-center items-center bg-white rounded-full w-5 h-5 font-bold pb-0.5'>+</div>
   </figure>
   <span className='flex justify-between'>
    <p className='text-sm font-light'>{data.title}</p>
    <p className='text-sm font-medium'>{'$'+data.price}</p>
   </span>
  </div>
 );
};

Personalmente le agregue un Loader de la libreria React Spinners (https://mhnpd.github.io/react-loader-spinner/docs/intro). Por si hay un retraso en la llamada a la API.

useState

Muy buena explicaci贸n de API.

As铆 vamos鈥

https://dummyjson.com/ Es una muy buena alternativa a la api de platzi, la recomiendo, esta muy completa!.

creo que deber铆an quitarle la opci贸n a la fakeapi de eliminar los productos, porque probando el api con postman solo existe un producto en el momento en que estoy viendo el curso, al parecer vandalizan mucho este api

Hola, ya solo hay 2 productos como respuesta del API

Con TypeScript es divertida la cosa. Me gusta la mezcla de async/await con try/catch para peticiones. ```js import React, { useEffect, useState } from 'react' import { Layout } from '../../Components/Layout' import { Card } from '../../Components/Card' import { ProductProps } from '../../Interfaces'; export const Home:React.FC=()=> { const [items, setItems] = useState<ProductProps[]>([]); useEffect(() => { const getData = async () => { try{ const response = await fetch("https://api.escuelajs.co/api/v1/products"); if(!response.ok){ throw new Error("We can't get data from the server"); } const data:ProductProps[] = await response.json(); setItems(data); console.log(data); }catch(error){ console.error(error); } } getData(); },[]) return ( <Layout> <h1 className="text-3xl font-semibold text-slate-800 w-full text-center mt-12 mb-6 ">Soy el home
{items.map((item:ProductProps)=>( item.images.length > 0 && !item.images[0].startsWith("[") && <Card title={item.title} price={item.price} img={item.images[0]} category={item.category.name} key={item.id} /> ))}
</Layout> ) } ```import React, { useEffect, useState } from 'react'import { Layout } from '../../Components/Layout'import { Card } from '../../Components/Card'import { ProductProps } from '../../Interfaces'; export const Home:React.FC=()=> {聽 const \[items, setItems] = useState\<ProductProps\[]>(\[]); 聽 useEffect(() => {聽 聽 const getData = async () => {聽 聽 聽 try{聽 聽 聽 聽 const response = await fetch("https://api.escuelajs.co/api/v1/products");聽 聽 聽 聽 if(!response.ok){聽 聽 聽 聽 聽 throw new Error("We can't get data from the server");聽 聽 聽 聽 }聽 聽 聽 聽 const data:ProductProps\[] = await response.json();聽 聽 聽 聽 setItems(data); 聽聽 聽 聽 聽 console.log(data);聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 }catch(error){聽 聽 聽 聽 console.error(error);聽 聽 聽 }聽 聽 }聽 聽 getData();聽 },\[]) 聽 return (聽 聽 \<Layout>聽 聽 聽 \<h1 className="text-3xl font-semibold text-slate-800 w-full text-center mt-12 mb-6 ">Soy el home\聽 聽 聽 \
聽 聽 聽 聽 {items.map((*item*:ProductProps)=>(聽 聽 聽 聽 聽 item.images.length > 0 && !item.images\[0].startsWith("\[") &&聽 聽 聽 聽 聽 聽 \<Card 聽 聽 聽 聽 聽 聽 聽 title={item.title}聽 聽 聽 聽 聽 聽 聽 price={item.price}聽 聽 聽 聽 聽 聽 聽 img={item.images\[0]}聽 聽 聽 聽 聽 聽 聽 category={item.category.name}聽 聽 聽 聽 聽 聽 聽 key={item.id}聽 聽 聽 聽 聽 聽 />聽 聽 聽 聽 ))}聽 聽 聽 \
聽 聽 \</Layout>聽 )}
lo hice un poco distinto, despues de pasarle el accesorio al componente Card lo us茅 de esta manera: ![](https://static.platzi.com/media/user_upload/image-85982391-75ce-41e0-b764-30898f6127d6.jpg) Lo trato como un objeto desde los argumentos de Card lo que me permite no usar data.data que considero no se ve de la mejor manera
Hola teff necesito ayuda con este caso donde al momento de realizar la consulta a la api si no incluyo la card me funciona bien, cuando intento iterar los datos con la card se me rompe todo ![](https://static.platzi.com/media/user_upload/image-beb3fbbc-d330-4786-b229-d35e9ee9b6f5.jpg) ![](https://static.platzi.com/media/user_upload/image-3728c39c-cbf9-49cf-b21f-635088dd573f.jpg) ![](https://static.platzi.com/media/user_upload/image-3680037d-8849-4950-bd8a-f0ec21720023.jpg) ![](https://static.platzi.com/media/user_upload/image-0a5a1e45-258e-45ec-84c7-4905680ed81d.jpg)
Tengo una pregunta ya que no me deja avanzar: Hola teff necesito ayuda con este caso donde al momento de realizar la consulta a la api si no incluyo la card me funciona bien, cuando intento iterar los datos con la card se me rompe todo ![](https://static.platzi.com/media/user_upload/image-15ed5054-0709-45d2-b83e-cc37024d66ad.jpg) ![](https://static.platzi.com/media/user_upload/image-9721a52b-1859-4485-933a-0d96276feb8a.jpg) ![]()![](https://static.platzi.com/media/user_upload/image-600d3272-ce73-488c-baf4-1b77d05c5746.jpg) ![](https://static.platzi.com/media/user_upload/image-a744b64a-99fd-4706-82c0-91437560e25d.jpg) que puedo hacer en este caso ya que tengo la misma consulta con otras Api y me funcionan bien.
Por alguna razon no me cargan algunas imagenes. Si alguien me puede ayudar, Gracias. El codigo no tiene ningun error aparentemente todo normal.![](https://static.platzi.com/media/user_upload/Captura%20de%20pantalla%202024-05-14%20144639-2cfeb1e9-da7e-45d1-92ad-788f30ca9d87.jpg)
la api de platzi no funciona, estaba buena para usarla pero tuve que usar Fake Store que es un poco mas simple
![](https://static.platzi.com/media/user_upload/image-db787ad7-958e-4084-b3a5-baac2bc16533.jpg)
El api de productos tiene un error en el primer item, en el array de imagenes. FYI ![](https://static.platzi.com/media/user_upload/image-dd4d6d60-c4b9-4493-8376-592494bd7f83.jpg)
Hola si alguien me puede ayudar se lo agradecer铆a, estoy haciendo las card y esto es lo que me sale usando diferentes enlaces para extraer el contenido de las card ![](https://static.platzi.com/media/user_upload/image-bdad3f7b-ec09-425a-87cb-7b6348bc1a2f.jpg) este es mi Home ![](https://static.platzi.com/media/user_upload/image-02cabecb-8c6d-4c55-a7c0-6f2d4c7f6a09.jpg) y este es mi card ![](https://static.platzi.com/media/user_upload/image-5d76c081-8bc5-46f3-a085-70ab48ddffca.jpg) he probado barias cosa incluso desestructuraci贸n y no me funciona
![](https://static.platzi.com/media/user_upload/image-2717b1b3-299e-40d1-b0fc-d6fd9903945e.jpg) ![](https://static.platzi.com/media/user_upload/image-0e84063b-e0da-480e-a61c-44ab5e531f28.jpg)
Para hacerlo responsive automaticamente solo utilice las siguientes clases ```js <Layout>

Home

{ items?.map((item)=>{ return (<Card key={item.id} data={item} />); }) }
</Layout> ```\<Layout>聽 聽 聽 \

Home\

聽 聽 聽 \
聽 聽 聽 聽 {聽 聽 聽 聽 聽 items?.map((item)=>{聽 聽 聽 聽 聽 聽 return (\<Card key={item.id} data={item} />);聽 聽 聽 聽 聽 })聽 聽 聽 聽 }聽 聽 聽 \
聽 聽 \</Layout>
驴Alguien podr铆a ayudarme, por favor? Los datos de la api se est谩n trayendo correctamente pero nunca llegan a agregarse al estado, puse un log para ver si tiene datos y aparece null. 聽 ```js import { useState, useEffect } from "react"; import Card from "../../Components/Card"; function Home() { const [items, setItems] = useState(null); useEffect(() => { const getProducts = async () => { try { const data = await fetch('https://api.escuelajs.co/api/v1/products') const jsonData = await data.json() setItems(jsonData) } catch (error) { console.log(error) } } getProducts() }, []) return ( <> Home <section className='grid gap-4 grid-cols-4 w-full max-w-screen-lg'> { items?.map(item => { <Card key={item.id} data={item} /> }) } </section> ) } export default Home ```
![](https://static.platzi.com/media/user_upload/image-c509fdf2-04dd-467e-a01f-c64c9c0792c6.jpg) lo que mencionaba German es muy cierto miren ahora como esta retornando la api en data.data.images!
Hago una petici贸n en son de paz... Deberian reestablecer la API original de FakeStore de Platzi con su gran contenido y calidad para poder trabajar tranquilos en el proyecto. Y hacer otra totalmente rompible, que se puede eliminar, actualizar y crear lo que quieran, pero que sea cuesti贸n de cada uno. Dar铆a mas sentido y placer seguir la clase de esa manera que estar dependiendo de otra API que tiene algunas diferencias o no se amoldan algunos aspectos. En fin, probablemente no cambie nada con esto pero al menos pueda coincidir con otro compa帽ero. Saludos!
A. mi me funciono la categoria solo usando data.data.category.name, lo demas esta igual q el video
ame esta explicaci贸n: \- "...Oye API hola..."
function Card({data}) { 聽 聽 聽 // Guard clause to prevent errors if data is not yet available:聽 聽 if (!data) return \
Loading...\
;
Parece que la API ha mejorado un poco, los nombres ahora corresponden a la imagen. El problema que ten铆a es que no estaba cargando las imagenes desde el item #31 en adelante, as铆 que he cortado la cantidad de objetos que que se le piden a a la API con slice. useEffect (()=> {聽 聽 fetch('https://api.escuelajs.co/api/v1/products')聽 聽 .then(response => response.json())聽 聽 .then(data => setItems(data.slice(0, 28))聽 聽 ) 聽 }, \[])
![]()![](<Captura de Pantalla 2024-01-24 a la(s) 12.54.34 p.m.>)Por el momento as铆 va quedando mi p谩gina ![](https://static.platzi.com/media/user_upload/Captura%20de%20Pantalla%202024-01-24%20a%20la%28s%29%2012.54.34%20p.m.-67f2284d-c3a0-4f17-8637-faa03972096a.jpg)
![](https://static.platzi.com/media/user_upload/image-3bf0e664-ca8b-4f44-b235-8d210c3601b0.jpg)
Si a alguien le est谩 dando problemas/productos incompletos del api de platzi, as铆 se pueden cambiar a Faker Store (es gratis). Este es el nuevo endpoint a apuntar: `'https://fakestoreapi.com/products'` . En el Home no hay que hacer ning煤n cambio extra. En el Card, les recomiendo para no usar `data.data` que des-estructuren las props as铆 `const Card = ({data}) => {`, y dentro del component estas son las nuevas propiedades sacadas de FakeStore : `const { category, image, title, price } = data;` Y ya solo reemplazan las del video por estas de arriba, si quieren agregar los propTypes del componente para quitar el warning de ESLint, son las siguientes: `Card.propTypes = { ` `data: PropTypes.objectOf({` `category: PropTypes.string,` `image: PropTypes.string,` `title: PropTypes.string,` `price: PropTypes.number, ` `}),` `}`
![](https://static.platzi.com/media/user_upload/image-9de2c3d9-0579-408b-8243-5d25d44be4aa.jpg) ![](https://static.platzi.com/media/user_upload/image-b4cd51db-9306-4992-b371-0d263df5da9c.jpg) preferi usar flex para ubicar las cards
Podemos usar una variable de entorno para guardar nuestro link de la api,contrase帽as,etc. Por defecto vite tiene dotenv en su sistema. Te explico como usarlo no necesitas instalar nada. 1. Creamos un archivo .env 2. Creamos una variable global, segun la documentaci贸n de vite la variable debe de tener VITE\_ adelante del nombre para ser expuesta por el framework. 3. Nombramos la varible y su contenido en mi caso. `VITE_URL_FAKE_API = 'https://fakestoreapi.com/products';` 4. En la vista que la queremos usar no necesitamos importar nada solo llamamos a la variable de esta forma. `fetch(import.meta.env.VITE_URL_FAKE_API);` Espero sea util, recuerda nunca pares de aprender.
![](https://static.platzi.com/media/user_upload/image-d3904550-de35-4018-8f35-613689705497.jpg) asi quedo mi dise帽o
Aqui dejo mi aporte usando la Api de Pokemon![](https://static.platzi.com/media/user_upload/Home-1ecaee78-fbf5-4b69-a32e-50365734d196.jpg)
Muchachos para limpiar un poco el listado de productos , podemos hacer la peticion DELETE al endpoint https://api.escuelajs.co/api/v1/products/\<id>, donde id es el id del producto, esto hara que los productos randoms no aparezcan en la peticion GET
Osea que un producto real si necesitamos crear la api para consumir la propia ?? o hay otras opciones
![](https://static.platzi.com/media/user_upload/image-ea92b543-9629-47f4-80c4-533087412eaa.jpg)![](https://static.platzi.com/media/user_upload/image-46ab9fd7-473b-492d-b1ca-8fab475031e3.jpg)

mi avance 馃槂 [](

![](https://static.platzi.com/media/user_upload/image-b3ab3eee-5a7b-4e39-aab5-58b8386d882b.jpg)
Pregunta 驴puedo tener almacenados los productos en un servicio como firebase? y de ser as铆, 驴c贸mo se conecta?

Yo personalmente trabaje las clases del div que contiene las cartas ya que al hacer resize o verse en diferentes dispositivos las cartas se sobreponen una encima de otra y dem谩s.
Para ello genere un archivo index.css para el Home el cual contiene el siguiente c贸digo.

.container_cards{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: 30px;
    width: 95%;
    justify-items: center;
}

Esto hace que no tengamos que usar un media-query para ir cambiando las columnas que tienen que generarse, sino que depende de la pantalla estas se acomodoran automaticamente.

Ahora al hacer esto toca pensar que el navbar tenemos que modificarlo si tambi茅n queremos que se vea bien desde un dispositivo mas peque帽o.

ome un hook personalizado que publico compa帽ero y lo integre, este recibe un par谩metro que es la url del endponit

import { useEffect, useState } from 'react';
export const useFetch = (url) => {
	const [data, setData] = useState();
	useEffect(() => {
		fetch(url)
			.then(res => res.json())
			.then(data => setData(data));
	}, [url]);

	return data;
};


cree un archivo para la ruta de la api y poder acceder a los diferentes endpoint

// Defin铆 UrlApi como un objeto en lugar de un array. Esto permitir谩 acceder a UrlApi.getProduct de manera adecuada.
const UrlApi = {
    getProduct: 'https://fakestoreapi.com/products',
};
export default UrlApi;

Asi Vamos, con la Fake Store API

Buenas, queria compartir mi callback del useEffect que lo hice un poco distinto. A mi me gusto mas de esta forma:

  useEffect(() => {
    const getProducts = async () => {
      const response = await fetch('https://api.escuelajs.co/api/v1/products');
      const data = await response.json();
      
      setItems(data);
      console.log(items);
    };
    getProducts();
  }, []);

La API de FakeStore no es disponible 馃槕

Hola la API de platzi no ha estado funcionando bien. Puedes usar este peque帽o servidor si gustas para consumir una API desde tu propia computadora.
https://github.com/FranciscoJSB12/Ecommerce-backend
Te dej茅 un readme con las instrucciones para usarlo, as铆 podr谩s seguir con tu curso normalmente, son bastantes sencillas.

Estoy armando una pricing page, en este caso no use el API de platzi, sin embargo le paso los datos de la siguiente manera


const data_princing_cards = [
  {
  'id':1,
  'plan':'Free',
  'benefits':['Benefit 1', 'Benefit 2', 'Benefit 3'],
  'price':10,
  },
  {
  'id':2,
  'plan':'Hobby',
  'benefits':['Benefit 1',  'Benefit 3'],
  'price':20,
  },
  {
  'id':3,
  'plan':'Standard',
  'benefits':['Benefit 1', 'Benefit 2', 'Benefit 3'],
  'price':30,
  },

]

function Pricing() {
  const [items, setItems] = useState(null)

  useEffect(() => {
    setItems(data_princing_cards)
  }, [])

Esta es mi tiendo: https://store-practice-dr.netlify.app/

馃槂

Que mal, no me salen los 200 productos 馃槶馃様

Yo llevo mi ecommerce as铆, pero con flexbox.
No s茅 por qu茅 se me dificulta m谩s con grid.

Esto es asombroso!

Hay problemas con la API, no sale bien la informacion, la imagen no corresponde a la informacion y en la mitad de la pagina ya no sale informacion

Para las personas que les gusta usar Async/Await

  useEffect(() => {
    async function fetchProduct() {
      const response = await fetch("https://api.escuelajs.co/api/v1/products");
      const data = await response.json();
      setProducts(data);
    }

    fetchProduct();
  }, []);

Para usar axios solo debemos importarlo
npm install axios y luego usarlo en el useEffect
useEffect(() => {
const apiUrl = 鈥https://tu-url-de-api.com/鈥;

axios.get(`${apiUrl}activos`)
  .then(response => {
    setAssets(response.data);
  })
  .catch(error => {
    console.error('Error fetching assets:', error);
  });

}, []);

Una pena que la api la est茅n modificando constantemente entorpeciendo el resultado final. Literalmente tuve que buscar una api externa para poder seguir

)

Card component

const Card = ({ product }) => {
  const { category, images, title, price } = product

  return (
    <div className="bg-white cursor-pointer w-56 h-60 rounded-lg">
      <figure className="relative mb-2 w-full h-4/5">
        <span className="absolute bottom-0 left-0 bg-white/60 rounded-lg text-black text-xs m-2 px-3 py-0.5">
          {category.name}
        </span>
        <img className="w-full h-full object-cover rounded-lg" src={images[0]} alt={title} />
        <div className="absolute top-0 right-0 flex justify-center items-center bg-white w-6 h-6 rounded-full m-2  p-1">
          +
        </div>
      </figure>
      <p className="flex justify-between">
        <span className="text-sm font-light">{title}</span>
        <span className="text-lg font-medium">${price}</span>
      </p>
    </div>
  )
}

export default Card

Qued贸 genial! por ahora solo me trae 20 elementos !

https://api.escuelajs.co/api/v1/products
iba ausar la API Fake Store de platzi pero simplemente esta vacia, si pongo la url en el navegador me devuelve un arreglo vacio, como lleno entonces mis componentes card