javascriptreactjsfetch-apiastrojs

Dynamic API using Astro and React


I've recently started my web dev journey, and decided to learn some JavaScript to mess with APIs in order to learn how to perform the fetch (for starters) from a public API. My first attempt at this is by trying to integrate a live BTC API in my portfolio. Although ChatGPT says this is correct and the information should be displayed, the is nothing being displayed besides the title. API - CoinDeskAPI.

This is my CoinDeskAPI.jsx component:

import { useEffect, useState } from "react";

export const CoinDeskAPI = () => {
  const [btcData, setBtcData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.coindesk.com/v1/bpi/currentprice.json');
        if (!response.ok) {
          throw new Error('Failed to fetch Bitcoin data');
        }
        const data = await response.json();
        setBtcData(data);
      } catch (error) {
        console.error('Error fetching Bitcoin data:', error);
      }
    };

    fetchData();
  }, []);

  return (
    <article className="flex flex-col gap-2 flex-grow">
      <header className="flex w-full flex-row justify-between gap-2">
        <h3 className="text-xl text-neutral-950">
          API Testing (<a className="hover:text-blue-500 after:content-['_↗']" href="https://api.coindesk.com/v1/bpi/currentprice.json" target="_blank" rel="noreferrer"> CoinDeskAPI</a>)
        </h3>
      </header>
      <p className="w-auto max-w-[60ch] leading-6 text-base">Displaying live BTC values, first API test!</p>
      
      <article>
        {btcData && (
          <ul>
            <li>BTC Rate (USD): {btcData.bpi.USD.rate}</li>
            <li>BTC Rate (EUR): {btcData.bpi.EUR.rate}</li>
            <li>BTC Rate (GBP): {btcData.bpi.GBP.rate}</li>
          </ul>
        )}
      </article>

    </article>
  );
};

and this is how I'm passing it to my index.astro file:

---
...other imports

import { CoinDeskAPI } from "../components/CoinDeskAPI.jsx";
---


<Layout title="Portfolio">
    <main class="flex flex-col gap-20">
          
                <!-- More code...  -->
            
        <!-- Bitcoin API section -->
        <CoinDeskAPI />
                
        
          
        </main>
</Layout>

Solution

  • To make a React component interactive, Astro requires you to load it like:

    <CoinDeskAPI client:load />
    

    Note that if you load data in the React component (with useEffect), it will make the request only after the basic page is loaded in the user's browser and will make the request from the browser. To speed things up, do the request form the server and pass it as a prop to the component:

    ---
    import { CoinDeskAPI } from "../components/CoinDeskAPI.jsx";
    
    const data = await fetch('https://api.coindesk.com/v1/bpi/currentprice.json').then(res => res.json());
    ---
    
    <CoinDeskAPI client:load btcData={data} />
    

    Note that in the provided example, you don't seem to make any client-side interactivity. If so, you don't need React at all, just Astro components that run on the server are enough.