Is there a way to make the data fetch only once to avoid API calls limit?

Viewed 75

I have these codes trying to implement a crypto return calculator that takes in a coin ID, a buy and sell date and the coin amount.

My issue is that the API is being fetched after every input and by the time I reach the sell date, my API limit has been reached.

Is there a way to prevent this from happening?
Here are the codes below.

    export default function App() {
      const [trade, setTrade] = useState({
        sellData: {},
        buyData: {},
        gains: 0
      });
    
      const coinList = [
        { id: 0, name: "bitcoin" },
        { id: 1, name: "ethereum" },
        { id: 2, name: "tezos" },
        { id: 3, name: "cardano" }
      ];
    
      const [buyDate, setBuyDate] = useState("");
      const [sellDate, setSellDate] = useState("");
      const [volume, setVolume] = useState(0);
      const [coin, setCoin] = useState("");
    
      const coingeckoUrl = (coin, date) => {
        return `https://api.coingecko.com/api/v3/coins/${coin}/history?date=${date}&localization=false`;
      };
    
      const calcGains = () => {
        setTrade({
          ...trade,
          gains:
            (trade.sellData.market_data?.current_price.usd -
              trade.buyData.market_data?.current_price.usd) *
            volume
        });
      };
    
      const coingeckoFetch = async (buy, coin, date) => {
        fetch(coingeckoUrl(coin, date)).then((response) =>
          response.json().then((jsonData) => {
            if (buy) {
              setTrade({ ...trade, buyData: jsonData });
            } else {
              setTrade({ ...trade, sellData: jsonData });
            }
          })
        );
      };
      const handleBuyChange = (e) => {
        let val = e.target.value;
        setBuyDate(val);
        coingeckoFetch(true, coin, val);
      };
    
      const handleSellChange = (e) => {
        let val = e.target.value;
        setSellDate(val);
        coingeckoFetch(false, coin, val);
      };
    
      const handleCoinChange = (e) => {
        let val = e.target.value;
        setCoin(val);
        coingeckoFetch(null, coin, val);
      };
      return (
        <div className="App">
          <select defaultValue={coin} onChange={(val) => handleCoinChange(val)}>
            {coinList.map((item) => (
              <option key={item.id}>{item.name}</option>
            ))}
          </select>
          <input
            placeholder="Insert Buy Date"
            defaultValue={buyDate}
            onChange={(val) => handleBuyChange(val)}
          />
          <h3> {trade.buyData.market_data?.current_price.usd} USD</h3>
    
          <input
            placeholder="Insert Sell Date"
            defaultValue={sellDate}
            onChange={(val) => handleSellChange(val)}
          />
          <h3> {trade.sellData.market_data?.current_price.usd} USD</h3>
    
          <input
            placeholder="Insert Amount of Tokens"
            value={volume}
            onChange={(e) => setVolume(e.target.value)}
          />
          <h3>{volume}</h3>
          <button onClick={calcGains}> Calculate </button>
          <h3>{trade.gains} USD</h3>
        </div>
      );
    }

Thank you for your help.

1 Answers

Summary

if you are just don't want to request too many times.

Maybe you can add a state like

const [fetchNow, setFetchNow] = useState(false);

And in your handleChange() functions, do not carry out the coingeckoFetch(). But execute the setFetchNow() like this

      const handleBuyChange = (e) => {
        let val = e.target.value;
        setBuyDate(val);
        
        // or your buy condition
        if (val) {
          setFetchNow(true)
        }
      };
    
      const handleSellChange = (e) => {
        let val = e.target.value;
        setSellDate(val);

        // or your sell condition
        if (val) {
          setFetchNow(true)
        }
      };
    
      const handleCoinChange = (e) => {
        let val = e.target.value;
        setCoin(val);

        // or your coin condition
        if (val) {
          setFetchNow(true)
        }
      };

Then add a useEffect(), and use a conditional if statement to determine that whether the coingeckoFetch() be carry out or not

useEffect(()=>{
  if (fetchNow) {
  coingeckoFetch(true, coin, val);
  }
}, [fetchNow]);

Other

Or just simply add conditional if statement in your coingeckoFetch()

like

 const coingeckoFetch = async (buy, coin, date) => {
        // conditional if statement
        if (buy !== "MyCondition") {
          return;
        }
        else if (coin !== "MyCondition") {
          return;
        }
        else if (date !== "MyCondition") {
          return;
        }
        
        fetch(coingeckoUrl(coin, date)).then((response) =>
          response.json().then((jsonData) => {
            if (buy) {
              setTrade({ ...trade, buyData: jsonData });
            } else {
              setTrade({ ...trade, sellData: jsonData });
            }
          })
        );
      };
Related