Docs de la API 👉 https://api.escuelajs.co/docs/
API para desarrollo 👉 https://api.escuelajs.co/api/v1/
Introducción a React
¿Qué es React.js?
Conceptos fundamentales de React
Quiz: Introducción a React
Configurando el entorno de desarrollo para React
Análisis de dependencias en proyectos de React
Instalación de React y React DOM
Configuración de Webpack y Babel
Cambios en tiempo real con Webpack
React con CSS y Sass
Quiz: Configurando el entorno de desarrollo para React
Maquetación en React
Transformando HTML y CSS en componentes de React
Estilos en los componentes de React
Quiz: Maquetación en React
Páginas, rutas y componentes
React Router DOM
Navegación entre rutas
Header en todas las rutas
¿Qué es Atomic Design? Conoce los beneficios
Solución al reto: componentes y rutas de React Shop
Tipos de componentes en React: stateful vs. stateless
Imágenes y alias en Webpack
Quiz: Páginas, rutas y componentes
Lógica con React Hooks
React.useState
Toggle del menú
useEffect y consumo de APIs
Custom Hooks para la tienda
useRef y formularios
React Context
Completando el carrito de compras
Orden de compra
Calculando el precio total
Eliminando productos del carrito
Quiz: Lógica con React Hooks
Deploy
Cómo comprar tu dominio y conexión con Cloudflare
Automatizando el despliegue con GitHub Actions
Próximos pasos
Retos de React.js (bug hunters)
Continúa con el Curso Práctico de Next.js
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 45
Preguntas 18
Docs de la API 👉 https://api.escuelajs.co/docs/
API para desarrollo 👉 https://api.escuelajs.co/api/v1/
useEffect es una manera de que nuestro componente de React, puede recibir nueva info, re-renderizar o cambiar su contenido, cuando una función se haya completado. Es decir, podemos controlar el momento en el cual nuestro componente tome un cierto comportamiento. Por ejemplo, en situaciones como funciones asíncronas ⇒ setTimeout o asyn y await, fetch requests o manipulaciones del DOM. Veamos un ejemplo de como usar useEffect.
Instalar axios para realizar peticiones get, también instalar el plugin de babel para manejar el asincronismo
npm install axios
npm install @babel/plugin-transform-runtime
Editemos rápidamente .babelrc
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-transform-runtime"
]
}
Ahora si veamos como funciona.
// ProductList.jsx
import React, { useEffect, useState } from 'react';
import ProductItem from '@components/ProductItem';
import axios from 'axios';
const API = 'https://api.escuelajs.co/api/v1/products';
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(async () => {
const response = await axios(API);
setProducts(response.data);
}, [])
return (
<section className="main-container">
<div className="ProductList">
{products.map(product => (
<ProductItem />
))}
</div>
</section>
);
}
En el inicio estamos importando axios para las peticiones, y creando una constante API que será la necesaria para traer información de los productos
Analicemos el componente productList. Al inicio creamos la estructura inicial de estado, en la cual guardaremos los artículos que traeremos de nuestra API. Ahora, como indicamos, useEffect es muy útil para peticiones HTTP. Para ello, creamos la función anónima que usa useEffect. Por dentro creamos la función que usara async. Dentro creamos una constante llamada response a la cual creamos la petición y guadamos el resultado de la API. A continuación, usamos setProducts para poder guardar la información nueva en products, por eso por dentro le pasamos response.data. Lo más destacable viene ahora, en el momento que pasamos un segundo argumento a useEffect.
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(async () => {
const response = await axios(API);
setProducts(response.data);
}, [])
}
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(async () => {
const response = await axios(API);
setProducts(response.data);
},)
}
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(async () => {
const response = await axios(API);
setProducts(response.data);
}, [props, state])
}
Tienen relación a la manera de anterior de componentes con clase
Usar la manera de array con datos o sin datos son equivalentes a componentDidUpdate o componentDidMount. Así como indica sus nombres ⇒
Es importante que si usan:
{products.map((product) => (
<ProductItem />
))}
estén utilizando ( ) en la función para regresar el jsx,
si usan { } deben utilizar la palabra return así:
{products.map((product) => {
return <ProductItem />;
})}
para los que vienen del futuro poner async dentro del useEffect da un error y se puede solucinar así:
useEffect(() => {
getData();
}, []);
const getData = async () => {
const response = await axios.get(API);
setProducts(response.data);
console.log(response);
};
Actualmente el useEffect no puede retornar una promesa, por ende el codigo debe ser asi:
useEffect(() => {
const getProducts = async () => {
const response = await axios(API);
setProducts(response.data);
};
getProducts();
}, []);
https://www.youtube.com/watch?v=_2hp91tJGpg
Async & Await
Aqui los comandos compañeritos:
-npm i axios
-npm install @babel/plugin-transform-runtime
Hay algo que falto y que en React es importante, el key de cada elemento renderizado dentro del map =>
<div className="ProductList">
{
products.map( product => (
<ProductItem key={ product.id } />
))
}
</div>
Desde 10:05 hasta 10:22 se filtra un sonido raro en el video, que miedo.
Documentación de la API: https://api.escuelajs.co/docs/
Constante de la API:
const API = 'https://api.escuelajs.co/api/v1/products';
Luego declarar las variables para el useState
const [products,setProducts] = useState([]);
Tienen que instalar axios
Documentación de axios: https://axios-http.com/docs/intro
npm install axios
Solicitud GET
useEffect(async ()=>{
const response = await axios(API);
setProducts(response.data);
},[])
Para recorrer el array de productos se usa el map
{products.map(product =>(
<ProductItem />
))}
También puedes utilizar esta API
https://fakestoreapi.com/
useEffect es la forma en la manejamos el ciclo de vida de un componente, en este caso nuestro componente contenedor que contiene otros componentes (los productos).
.
Si alguna vez trabajaron con los metodos del ciclo de vida de un class component, entender esta siguiente imagen les abrira la mente a entender de una vez por todas useEffect.
.
Abajo muestro un ejemplo de mi implementacion para este ejercicio:
Ey Oscar el termo de JavaScript que tenias en el escritorio de atras ya no está 😦
Podríamos decir que en está clase vimos levemente como integrar backend con frontend.
Es importante mencionar que existe un efecto llamado useLayoutEffect, todo el código que contiene se ejecuta una vez sea renderizado el componente. A diferencia de useEffect el cual se ejecuta justo antes del render. 😀💚
Si están usando React18 o >, useEffect no puede retornar promesas y al renderizar componentes mediante una ciclo usando map les pedirá usar un id. Pueden usar este código.
import React from 'react';
import { useEffect, useState } from 'react';
import {ProductItem} from '../components/ProductItem';
import '../styles/ProductList.scss';
import axios from 'axios';
const API = 'https://api.escuelajs.co/api/v1/products';
export const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(() => {
getProducts()
}, [])
const getProducts = async () =>{
const response = await axios(API);
setProducts(response.data);
};
return (
<section className="main-container">
<div className="ProductList">
{products.map((product, id)=>
<ProductItem key = {id}/>
)}
</div>
</section>
);
}
A mi me funciona sin instalar @babel/plugin-transform-runtime, será porque uso React 18?
Si por alguna razón no le lista los productos es mejor leer la API con fetch.
const obtenerDatos = async () => {
const data = await fetch(API);
const productos = await data.json();
setProducts(productos)
}
Una recomendación en el curso se hace uso de axios(URL_API) como método para traer elementos de la api, pero una api posee los demás métodos para realizar un crud, como lo es con el post para crear, el delete para eliminar y el put/patch para actualizar, así que una manera de llevar legible el código sería usar de esta forma la consulta a la api
useEffect(async () => {
const response = await axios.get(API);
setProducts(response.data);
}, [])
En lugar de:
useEffect(async () => {
const response = await axios(API);
setProducts(response.data);
}, [])
Comento esto porque me preguntaba como realizar un crud con react consumiendo la api, y me resultó esa duda, así que investigué la librería axios, y veo que de esa manera es que debería de usarse
Link de la documentación:
https://axios-http.com/docs/api_intro
Para los que estamos usando la ultima version de React, si no les funciona el codigo, cambien en la parte de useEffect por este codigo:
React.useEffect(() => {
async function fetchData() {
const response = await axios(API);
setProducts(response.data);
console.log(products)
}
fetchData();
console.log(products);
}, [])
y luego cuando retornan el componente (donde escriben la estructura ‘html’), coloquen:
{products.map((product) => {
return(
<ProductItem />
)
})}
con estos dos cambios deberia funcionar perfectamente
plugin babel:
npm install @babel/plugin-transform-runtime
React.UseEffect
Ejecuta el código que tengamos adentro justo antes de que React tiene todo listo para renderizar el componente
React.UseLayoutEffect
Ejecuta el código que tengamos adentro justo después de que React renderizo el componente
Para manejar los estados de request hacia una API:
Se necesitan 3 estados de carga:
El usar useEffect, con un arreglo vacío, es decir sin ninguna dependencia, es igual que cuando se usa componentDidMount en un class component.
useEffect(() => { ... }, []) === componentDidMount
Para que se ahorren el código del Lazy Loading. Ahora en nativo en HTML
<img src={product.images[0]} alt={product.name} loading="lazy" />
Para los que estén trabajando con Ts y quieran tipar de manera sencilla la api, usen app.quicktype.
Les comento que a mi no me renderizaban los elementos, sí lograba traer los datos de la API pero aún así no renderizaba.
Resulta que el problema estaba en la sintáxis de mi método ‘map’. Recuerden que siempre que usan llaves {…} para su arrow function, dentro debe haber un return. Mi problema era que no tenía un return y por eso ‘map’ no devolvía nada.
<div className="cards-container">
{products.map( product => {
return <ProductItem key={ product.id }/>
}) }
</div>
¿Qué hace useEffect? Al usar este Hook, le estamos indicando a React que el componente tiene que hacer algo después de renderizarse. React recordará la función que le hemos pasado (nos referiremos a ella como nuestro “efecto”), y la llamará más tarde después de actualizar el DOM. En este efecto, actualizamos el título del documento, pero también podríamos hacer peticiones de datos o invocar alguna API imperativa.
¿Por qué se llama a useEffect dentro del componente? Poner useEffect dentro del componente nos permite acceder a la variable de estado count (o a cualquier prop) directamente desde el efecto. No necesitamos una API especial para acceder a ella, ya que se encuentra en el ámbito de la función. Los Hooks aprovechan los closures de JavaScript y evitan introducir APIs específicas de React donde JavaScript ya proporciona una solución.
¿Se ejecuta useEffect después de cada renderizado? ¡Sí! Por defecto se ejecuta después del primer renderizado y después de cada actualización. Más tarde explicaremos cómo modificar este comportamiento. En vez de pensar en términos de “montar” y “actualizar”, puede resultarte más fácil pensar en efectos que ocurren “después del renderizado”. React se asegura de que el DOM se ha actualizado antes de llevar a cabo el efecto.
Fuentes: https://es.reactjs.org/docs/hooks-effect.html
al dia de hoy la api no esta regresando algunas imagenes, es problema de la api , de momento de mi aporte para que pongan una condición si no hay imagen que no se renderize el componente PorducItem
return (
<>
{product.images[0] !== "" ? (
<div className='ProductItem'>
<img src={product.images[0]} alt={product.title} />
<div className='product-info'>
<div>
<p>${product.price}</p>
<p>{product.title}</p>
</div>
<figure onClick={() => handleClick(product)}>
{state.cart.includes(product) ? (
<img
className='disabled add-to-cart-btn'
src={addedToCartImage}
alt='added to cart'
/>
) : (
<img
className='add-to-cart-btn pointer'
src={addToCartImage}
alt='add to cart'
/>
)}
</figure>
</div>
</div>
) : (
<></>
)}
</>
)
}
{
"presets": [
"@babel/preset-env",//Permite trabajar con eMAC 5 EMAC6
"@babel/preset-react"//Permite trabajar con React en sus nuevas y viejas versiones
],
"plugins":[
"@babel/plugin-transform-runtime"
]
}
Si a alguien le da error al instalar el plugin, intenten añadiéndole “” después de install.
A mi me funcionó de esta manera:
npm install “@babel/plugin-transform-runtime”
el que tenga este error y no sepa que hacer instale este plugin https://www.npmjs.com/package/node-polyfill-webpack-plugin y el que si sepa porfa me dicen porque pasa y si es la mejor solucion?
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.
Para tener en cuenta en caso de tener que llamar apis o peticiones cuya respuesta pueda llegar a tardar, dentro de un useEffect:
Enlace a la API:
Me parece genial que practiquemos como se puede consumir una api en este curso de react
Si no quieren instalar otra dependencia para usar async y await
pueden usar esta configuración en su .babelrc
😄:
{
"presets": [["@babel/preset-env", { "targets": { "node": "11" } }], "@babel/preset-react"]
}
Si le sale varios errores como a mi, por error en el identificador de los objetos dentro del array y por el performance de async y await, aca les dejo la solucion
import React, {useState, useEffect} from 'react';
import axios from 'axios';
import ProductItem from '@components/ProductItem';
import '@styles/ProductList.scss';
const API = 'https://api.escuelajs.co/api/v1/products';
const ProductList = () => {
const [products, setProducts] = useState([]);
useEffect(()=>{
const getProducts = async () => {
const response = await axios(API)
setProducts(response.data);
}
getProducts();
},[]);
return (
<section className="main-container">
<div className="ProductList">
{products.map(product => (
<ProductItem key={product.id}/>
))}
</div>
</section>
);
}
export default ProductList;
por conocimiento de otros cursos en ves de utilizar axios ando realizando las llamadas con fetch y asi practico mas, axios lo estube utilizando en su momento en produccion y traia mucha incompatibilidad.
No me gusta usar axios la verdad, con el simple pero poderoso fetch es mas que suficiente
useEffect(async () => {
const req = await fetch(URL_API)
const resp = await req.json()
setProducts(resp)
}, [])
Para los que estan usando Typescript
Aqui el useEffect,PD: es con funcion anonima:
useEffect(() => {
(async (): Promise<any> => {
const rta = await axios(API);
setProducts(rta.data);
})();
}, []);
si no aparecen los productos y copiaron el codigo de Oscar tal vez el problema sea este
{products.map((product) => (
<ProductItem />
))}
The useEffect Hook allows you to perform side effects in your components.
Some examples of side effects are: fetching data, directly updating the DOM, and timers.
useEffect accepts two arguments. The second argument is optional.
useEffect(<function>, <dependency>)
++Example:
++
import { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
});
return <h1>I've rendered {count} times!</h1>;
}
ReactDOM.render(<Timer />, document.getElementById('root'));
Ya no está disponible la API. Arroja error 404.
Ahora entiendo porque usan react:
Cuando hice este codigo dije, esto es lo mismo que se hacia en php.
<div className="ProductList">
{
products.map(product => (
<ProductItem />
))
}
</div>
Ya les cache a los de react developers, creo que tuvieron algún pasado con php jaja.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?
o inicia sesión.