No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

No se trata de lo que quieres comprar, sino de quién quieres ser. Invierte en tu educación con el precio especial

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

12 Días
15 Hrs
14 Min
6 Seg

Consumiendo la FakeStore API para pintar cards

8/31
Recursos

Aportes 109

Preguntas 19

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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} />
))}

Así voy con Nextjs, creo que está bonito.

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>

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 ‘useFetch’

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>
	);
};

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

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 }; ```

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

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

Alguien sabe en que curso se creo esta Api ? Yo estoy utilizando otra api porque esta esta rota fetch('https://fakestoreapi.com/products') .then(res=>res.json()) .then(json=>console.log(json))

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?

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.

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.

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()
  }, [])
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

![](https://static.platzi.com/media/user_upload/image-316afc67-82ba-49c2-83e5-51898eceb621.jpg) lo logre con <https://fakestoreapi.com/products> no entendi muy bien la api de Platzi :(
Así vamos profe.. ![](https://static.platzi.com/media/user_upload/image-e4553f08-4f5a-4898-9335-6373c58a8f2e.jpg)
Hola, muchas imágenes no están, el enlace sale roto
Me tocó usar otra API, porque solo me mostraba un único elemento ![](https://static.platzi.com/media/user_upload/image-c8fac3fe-8800-4ba3-9db5-cec229aa0d07.jpg)
No entiendo como pueden darnos una API que no funciona, quisiera saber si alguien lo pudo hacer como esta en el video hoy octubre 21 de 2024
Para los del problema con el tema de las imagenes con la API (Por cierto, esta malana. La ruta del video que nos dan es malisima, es decir, la imagienes no existen. Yo las coloque con esta data.data.category.images), pero si quieren ensayar con exprecioes regulares por el mal formato de la API, acá está: ```js const cleanImagesArray = (images) => { // Filtrar y mapear el array para limpiar cada string return images.map((img) => { // Eliminar comillas adicionales y corchetes si los hay let cleanedImage = img.replace(/["[\]\\]/g, '').trim(); return cleanedImage; }); }; const cleanedImages = cleanImagesArray(data.data.images); ```  const cleanImagesArray = (images) => {    // Filtrar y mapear el array para limpiar cada string    return images.map((img) => {      // Eliminar comillas adicionales y corchetes si los hay      let cleanedImage = img.replace(/\["\[\\]\\\\]/g, '').trim();      return cleanedImage;    });  };   const cleanedImages = cleanImagesArray(data.data.images);
Para los del problema con el tema de las imagenes con la API (Por cierto, esta malana. La ruta del video que nos dan es malisima, es decir, la imagienes no existen. Yo las coloque con esta data.data.category.images), pero si quieren ensayar con exprecioes regulares por el mal formato de la API, acá está:   const cleanImagesArray = (images) => {    // Filtrar y mapear el array para limpiar cada string    return images.map((img) => {      // Eliminar comillas adicionales y corchetes si los hay      let cleanedImage = img.replace(/\["\[\\]\\\\]/g, '').trim();      return cleanedImage;    });  };   const cleanedImages = cleanImagesArray(data.data.images);
![](https://static.platzi.com/media/user_upload/image-d22bd9d9-3461-452c-af20-83d06b858a42.jpg)
useEffect(() => { axios.get('https://api.example.com/data') .then(response => { console.log(response.data); }) .catch(error => { console.error('Error fetching data:', error); }); }, \[]);
Seria bueno declarar props type en cards ?
El api da problema con las imagenes ya que se le incluye un \[]
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)
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)
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
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.
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)
  }, [])

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);
  });

}, []);