Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso Práctico de React.js

Curso Práctico de React.js

Oscar Barajas Tavares

Oscar Barajas Tavares

useEffect y consumo de APIs

18/29
Recursos

Aportes 30

Preguntas 9

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

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.

Pre-configuración

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.

Maneras de usar useEffect

  • Array Vacío ⇒ ejecuta el callback solamente una vez, después de que el componente sea cargado en el DOM. Es decir, solamente cuando nuestro componente este cargado en el DOM, ejecutará la función por dentro SOLO UNA VEZ y nunca más
const ProductList = () => {
	const [products, setProducts] = useState([]);

	useEffect(async () => {
		const response = await axios(API);
		setProducts(response.data);
	}, [])
}
  • Sin argumentos ⇒ cuando usemos useEffect, pero sin segundo argumento, este ejecutará dicho callback cada vez que se re-rendirece en el DOM. Es decir, cada vez que cambie cualquier valor del componente, este callback siempre se ejecuta
const ProductList = () => {
	const [products, setProducts] = useState([]);

	useEffect(async () => {
		const response = await axios(API);
		setProducts(response.data);
	},)
}
  • Array con datos ⇒ este tipo se ejecuta solamente cuando un valor de prop o state de nuestro componente cambie. Es decir, imaginemos que existe un contador interno de clicks. Cada vez que el contador indique explicita mente que un valor del componente cambió, el callback de useEffect siempre se ejecutará.
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 ⇒

  • Si el componente se actualizó, este ejecuta un callback el cual tiene cierta función. Esta manera es igual a usar useEffect con un array con datos. Es decir, ¿hay nueva info? ⇒ realiza esto cada vez que la info nueva se actualice
  • Si el componente se cargó en el DOM, un callback será ejecutado y nunca más. Esta manera es igual a usar useEffect con un array sin datos. Es decir, ¿ya está cargado? ⇒ necesito que hagas esto y después te puedes quedar dormido

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

Aqui los comandos compañeritos:

-npm i axios
-npm install @babel/plugin-transform-runtime

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

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

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á 😦

También puedes utilizar esta API
https://fakestoreapi.com/

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. 😀💚

Podríamos decir que en está clase vimos levemente como integrar backend con frontend.

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
  • npm install axios
  • npm install @babel/plugin-transform-runtime

plugin babel:

npm install @babel/plugin-transform-runtime

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

Me parece genial que practiquemos como se puede consumir una api en este curso de react

React.UseEffect
Ejecuta el código que tengamos adentro justo antes de que React tiene todo listo para renderizar el componente

  • El segundo argumento que le enviamos al hook puede ser un array vacío [ ], este le dice al UseEffect que solo se ejecute la primera vez que el componente se renderize, cuando se rerenderize no se ejecutara. Si dejamos ese segundo argumento vacío, el hook se ejecutara todas las veces que nuestro componente se rerenderize.
  • Podemos ejecutarlo cuando hayan cambios específicos en cierta variable o cierto componente, para eso podemos poner como segundo argumento un arreglo y adentro el nombre de la variable: [TotalToDos].

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:

  1. Estamos cargando tu información
  2. Ya cargamos tu información pero tiene hubo un error
  3. Ya cargamos tu información y todo esta perfecto

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 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”

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>

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:

  • Lo que renderiza no lo agrega al código fuente, lo que genera problemas al no permitir que google indexe el mismo.
  • Si llamo una api que tarda mucho, el cliente va a ver una página en blanco hasta recibir el contenido.

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.

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

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.