Estoy tratando de conectar mi sitio con rapidAPI usando axios/fetch. Tengo varios componentes que debo hacer, por lo que necesito mantener mis números de referencia bajos. Dicho esto, soy un poco nuevo en las llamadas React y tanto mis llamadas axios como fetch están haciendo la misma llamada API varias veces, absorbiendo mis llamadas API en muy poco tiempo (500 en unos minutos de intentar solucionarlo, lol). No estoy seguro de cómo cambiar mi código para que funcione con async/await, y podría necesitar ayuda si esa es la mejor solución. Intenté usar cancelTokens, pero esto tampoco funciona. A continuación se muestra mi código usando cancelTokens con un tiempo de espera. Sé que esta NO es una manera buena y eficiente de remediar este problema, y necesito ayuda para solucionar lo que creo que es una solución fácil que simplemente no me ha encajado todavía. ¡Muchas gracias de antemano! aquí está mi componente Stock.tsx , que al final toma el precio de la cotización bursátil:
import React from "react"; import "../styles/Stock.css"; import axios from "axios"; import loader from "../graphics/loading.gif"; const { useState } = React; function Stock() { const [price, setPrice] = useState("0"); let options: any; const cancelToken = axios.CancelToken; const source = cancelToken.source(); options = { cancelToken: source.token, method: "GET", url: "https://yh-finance.p.rapidapi.com/stock/v2/get-summary", params: { symbol: "AAPL", region: "US" }, headers: { "x-rapidapi-host": "yh-finance.p.rapidapi.com", "x-rapidapi-key": "nonono:)", }, }; axios .request(options) .then(function (response) { console.log(response.data); setPrice(response.data.price.regularMarketPrice.fmt.toString()); }) .catch(function (error) { console.error("Error getting price: ", error); }); //i know, this is bad setTimeout(() => { source.cancel("TIME"); }, 2000); return ( <> {price === "0" ? ( <div> <img src={loader} alt="loading" className={"loader"} /> </div> ) : ( <div>AAPL: {price}</div> )} </> ); } export default Stock;Si se supone que su solicitud de red debe realizarse solo una vez cuando se monta el componente, este es el caso de uso para useEffect con una matriz de dependencia vacía:
Si desea ejecutar un efecto [...] solo una vez (en el montaje [...]), puede pasar una matriz vacía (
[]) como segundo argumento. Esto le dice a React que su efecto no depende de ningún valor de accesorios o estado, por lo que nunca necesita volver a ejecutarse.
import React, { useEffect } from "react"; // Within the body of your React functional component: useEffect(() => { axios.request(options) // etc. }, []); // 2nd argument is the dependency array, here emptyLa clave es el método useEffect. useEffect es una función que se ejecuta cuando una de las variables ha cambiado.
useEffect(() => { axios... }, []);Si el segundo parámetro es una lista vacía (lista de variables), el método se ejecutará una sola vez.
Una mejora sería usar useEffect sin el segundo parámetro y verificar si ya tiene los datos. De lo contrario, llamará cada vez que se esté procesando solo si no tiene los datos.
useEffect(() => { if (!loading && !data) { setLoading(true); axios....then(() => { .... setLoading(false); }).catch(function (error) { .... setLoading(false); }); } });espero haberte ayudado
Pruebe esta solución con referencias
import React,{useRef,useEffect} from "react"; import "../styles/Stock.css"; import axios from "axios"; import loader from "../graphics/loading.gif"; const { useState } = React; function Stock() { const stockRef = useRef(false); const [price, setPrice] = useState("0"); let options: any; const cancelToken = axios.CancelToken; const source = cancelToken.source(); options = { cancelToken: source.token, method: "GET", url: "https://yh-finance.p.rapidapi.com/stock/v2/get-summary", params: { symbol: "AAPL", region: "US" }, headers: { "x-rapidapi-host": "yh-finance.p.rapidapi.com", "x-rapidapi-key": "nonono:)", }, }; const fetchData = () => { if (stockRef && stockRef.current) return; stockRef.current = true; axios .request(options) .then(function (response) { console.log(response.data); setPrice(response.data.price.regularMarketPrice.fmt.toString()); }) .catch(function (error) { console.error("Error getting price: ", error); }); stockRef.current = false; } } //i know, this is bad setTimeout(() => { source.cancel("TIME"); }, 2000); useEffect(() => { fetchData(); },[]) return ( <> {price === "0" ? ( <div> <img src={loader} alt="loading" className={"loader"} /> </div> ) : ( <div>AAPL: {price}</div> )} </> ); } export default Stock;