skip to Main Content

I am designing a weather app as a resume project. I am trying to call WeatherAPI for current weather data as provided by their currentdata.json call. How do I actually do this in code?

I have a single page:

// /src/app/page.js
import Card from "@/lib/components/card";
import { fetchCurrentData } from "@/lib/data";

export default async function Page() {
  //fetching data...
  const currentWeather = await fetchCurrentData();

  //hardcoded card data for testing
  const currWeatherCardData = {
    top: 'Saturday, June 1st, 2024',
    main: '31u00b0C',
    bottom: 'Sunny'
  };
  //more card data constants for other cards, same top/main/bottom...

  return (
    <main className="flex flex-col m-24 gap-8">
      <Card data={currWeatherCardData}/> 
      <Card data={highLowsCardData}/>
      <Card data={precipCardData}/>
      <Card data={uviCardData}/>
    </main>
  );
}

I’m trying to get fetchCurrentData() to call the API.

// src/lib/data.ts
export async function fetchCurrentData() {
  try {
    const currentData = await fetch('https://api.weatherapi.com/v1/current.json?q=LOCATION&key=APIKEY');
    console.log(currentData.json())
    return currentData;
  } catch (error) {
    console.error('API Error: ', error);
    throw new Error('Failed to fetch current weather data.');
  }
}

fetchCurrentData() is returning a Response object, which I’m not quite sure how to parse and get it to page.js Specifically, for example, I’m not sure how to get the localtime from the JSON into one of the Cards as text.

For reference, the API GET request returns a JSON object that looks like:

{
  "location": {
    "name": "New York",
    "region": "New York",
    "country": "United States of America",
    "lat": 40.71,
    "lon": -74.01,
    "tz_id": "America/New_York",
    "localtime_epoch": 1717386775,
    "localtime": "2024-06-02 23:52"
  },
  "current": {
    "last_updated_epoch": 1717386300,
    "last_updated": "2024-06-02 23:45",
    "temp_c": 22.8,
    "temp_f": 73,
    "is_day": 0,
    "condition": {
      "text": "Partly cloudy",
      "icon": "//cdn.weatherapi.com/weather/64x64/night/116.png",
      "code": 1003
    },
    "wind_mph": 3.8,
    "wind_kph": 6.1,
    "wind_degree": 200,
    "wind_dir": "SSW",
    "pressure_mb": 1014,
    "pressure_in": 29.93,
    "precip_mm": 0,
    "precip_in": 0,
    "humidity": 59,
    "cloud": 75,
    "feelslike_c": 24.8,
    "feelslike_f": 76.6,
    "windchill_c": 22.8,
    "windchill_f": 73,
    "heatindex_c": 24.8,
    "heatindex_f": 76.6,
    "dewpoint_c": 13.9,
    "dewpoint_f": 57,
    "vis_km": 16,
    "vis_miles": 9,
    "uv": 1,
    "gust_mph": 6.3,
    "gust_kph": 10.2
  }
}

Is my approach best practice? Or is there a better way to do this?

Any help would very appreicated!

2

Answers


  1. Using API Calls Directly in Components
    If you prefer to make API calls directly within your components (e.g., in response to user actions), you can use fetch or axios:

    // pages/index.js
       import { useEffect, useState } from 'react';
        function HomePage() {
      const [data, setData] = useState(null);
    
      useEffect(() => {
        async function fetchData() {
          const res = await fetch('https://api.example.com/data');
          const currentWeather = await res.json();
          setData(currentWeather);
        }
        
        fetchData();
      }, []);
    
      if (!data) return <div>Loading...</div>;
    
      return (
        <div>
          <h1>Data from API</h1>
          {/* Use data as per need */}
          <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
      );
    }
    
    export default HomePage;
    
    Login or Signup to reply.
  2. The response object is usually a promise that should execute something when it’s fulfilled (in this case the promise is fulfilled once the external api send the values).

    To give an alternative to the async approach (I usually provide a function to execute):

    fetch('https://api.weatherapi.com/v1/current.json?q=LOCATION&key=APIKEY').then((r)=>{console.log(r);setSomeState(r)});
    

    Since you are working with a function I would give the function a function parameter to be executed. Something like:

    export function fetchCurrentData(onResult: (r) => void) {
        fetch('https://api.weatherapi.com/v1/current.json?q=LOCATION&key=APIKEY').then(onResult).catch(err => {
            // Handle errors
            console.error(err);
        });
    }
    

    In a component you could then call it with:

    export default function DummyComponent() {
        const [state, setState] = useState();
        const collectData = useCallback(() => {
            fetchCurrentData((r) => setState(r));
        }, []);
    
        return <button onClick={collectData}>Collect Data</button>
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search