Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Fetch Data with Type Safety in React

Last Updated: October 3, 2023

My project source code is available here

Overview

In this tutorial, we will learn how to fetch data with type safety in React using TypeScript and the Fetch API.

Files

BitcoinData.tsx

BitcoinData.tsx

import { useEffect, useState } from "react";

type bitcoinDataType = {
  time: {
    updated: string;
    updatedISO: string;
    updateduk: string;
  };
  disclaimer: string;
  chartName: string;
  bpi: {
    USD: {
      code: string;
      symbol: string;
      rate: string;
      description: string;
      rate_float: Number;
    };
    GBP: {
      code: string;
      symbol: string;
      rate: string;
      description: string;
      rate_float: Number;
    };
    EUR: {
      code: string;
      symbol: string;
      rate: string;
      description: string;
      rate_float: Number;
    };
  };
};

function BitcoinData() {
  // State
  const [coinData, setCoinData] = useState<bitcoinDataType>({
    bpi: {
      EUR: {
        code: "",
        description: "",
        rate: "",
        rate_float: 0,
        symbol: "",
      },
      GBP: { code: "", description: "", rate: "", rate_float: 0, symbol: "" },
      USD: { code: "", description: "", rate: "", rate_float: 0, symbol: "" },
    },
    chartName: "",
    disclaimer: "",
    time: { updated: "", updatedISO: "", updateduk: "" },
  });
  async function fetchData() {
    fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
      .then((response) => response.json())
      .then((data) => setCoinData(data))
      .catch((error) => console.log(error));
  }

  // Only fetch data on first render
  useEffect(() => {
    fetchData();
  }, []);

  useEffect(() => {
    console.log(coinData);
    console.log("length: ", Object.keys(coinData).length);
  }, [coinData]);

  return Object.keys(coinData).length === 0 ? (
    <div>
      <h1>Loading data</h1>
    </div>
  ) : (
    <div>
      <h1>{"USD: $" + coinData["bpi"]["USD"]["rate_float"]}</h1>
      <h2>{"Last Updated: " + coinData["time"]["updated"]}</h2>
    </div>
  );
}

export { BitcoinData };

App.tsx

This file simply renders the <BitcoinData /> component.

App.tsx

import React from "react";
import "./App.css";
import { BitcoinData } from "./BitcoinData";

function App() {
  return (
    <div className="App">
      <BitcoinData />
    </div>
  );
}

export default App;

index.tsx

This file is the entry point for the React application.

index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

References