skip to Main Content

I am trying to display weather api data from: (https://www.weatherapi.com/api-explorer.aspx#forecast)

import Image from "next/image"

interface Hour {
    time_epoch: number
    time: string
    temp_c: number
    temp_f: number
    is_day: number
    wind_mph: number
    wind_kph: number
    wind_degree: number
    wind_dir: string
    pressure_mb: number
    pressure_in: number
    precip_mm: number
    precip_in: number
    humidity: number
    cloud: number
    feelslike_c: number
    feelslike_f: number
    windchill_c: number
    windchill_f: number
    heatindex_c: number
    heatindex_f: number
    dewpoint_c: number
    dewpoint_f: number
    will_it_rain: number
    chance_of_rain: number
    will_it_snow: number
    chance_of_snow: number
    vis_km: number
    vis_miles: number
    gust_mph: number
    gust_kph: number
}


async function getHourlyForecast() {
  const location = 'Pemberton'
  const apiKey = '84703323c7f94238a98203306233010'
  const response = await fetch(`http://api.weatherapi.com/v1/forecast.json?key=${apiKey}&q=${location}&days=1&aqi=no&alerts=no` , {
    cache: 'no-cache',})
  const data = await response.json()
  return data 
}

export default async function Forecast() {
  const forecast = await getHourlyForecast()
  console.log(forecast);

  return (
     <div>
        <h2 className="text-center">Hourly Weather Forecast</h2>
        <div className="grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-7 gap-6">
        {forecast.forecastday.map((hour, index) => 
        (
          <div key={index} className="text-center rounded-lg flex flex-col items-center bg-green-950/25 p-10">
            <p>{new Date(hour.date).toLocaleString("en-US", { weekday: "short"})}</p>
            <img className="w-50 h-50"
              src={hour.hour.condition.icon}
              alt={hour.hour.condition.text}
              aria-label={hour.hour.condition.text}/>
            <div>
              <p className="bg-black/25 px-2 italic rounded-xl text-white mb-2">
                High:{" "}
                <span aria-label={`Maximum temperature: ${hour.hour.temp_c.toFixed()} degrees Celcius`}>
                  {hour.hour.maxtemp_c.toFixed()}°
                </span>
              </p>
              <p className="bg-black/25 px-2 italic rounded-xl text-white">
                Low:{" "}
                <span aria-label={`Minimum temperature: ${hour.hour.temp_c.toFixed()} degrees Celcius`}>
                  {hour.hour.temp_c.toFixed()}°
                </span>
              </p>
            </div>
          </div>
        ))}
        </div>
    </div>
   
  );
}

I am able to map data from Forecast.Current but I also want to map from Forecast.Forecastday.Day object but object comes back as undefined.
Can anyone help?

Tried: {forecast.forecastday.map((hour, index) =>
but got undefined.

2

Answers


  1. Just modify your code.

    export default async function Forecast() {
      const forecast = await getHourlyForecast();
      console.log(forecast);
    
      return (
        <div>
          <h2 className="text-center">Hourly Weather Forecast</h2>
          <div className="grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-7 gap-6">
            {forecast.forecast.forecastday.map((day, index) => (
              <div key={index} className="text-center rounded-lg flex flex-col items-center bg-green-950/25 p-10">
                <p>{new Date(day.date).toLocaleString("en-US", { weekday: "short" })}</p>
                <img
                  className="w-50 h-50"
                  src={day.day.condition.icon}
                  alt={day.day.condition.text}
                  aria-label={day.day.condition.text}
                />
                <div>
                  <p className="bg-black/25 px-2 italic rounded-xl text-white mb-2">
                    High:{" "}
                    <span aria-label={`Maximum temperature: ${day.day.maxtemp_c.toFixed()} degrees Celsius`}>
                      {day.day.maxtemp_c.toFixed()}
                    </span>
                  </p>
                  <p className="bg-black/25 px-2 italic rounded-xl text-white">
                    Low:{" "}
                    <span aria-label={`Minimum temperature: ${day.day.mintemp_c.toFixed()} degrees Celsius`}>
                      {day.day.mintemp_c.toFixed()}
                    </span>
                  </p>
                </div>
              </div>
            ))}
          </div>
        </div>
      );
    }
    

    One suggestion – If this component is rerendering frequently with the same data, you may use React Hook – useMemo to memoize the forecast data and avoid unnecessary re-renders. Please tell me if that works.

    Login or Signup to reply.
  2. To map over the forecastday and its nested properties, you need to make sure that each level of nesting exists and is not undefined.

    EXAMPLE

    export default async function Forecast() {
      const forecast = await getHourlyForecast();
      console.log(forecast);
    
      return (
        <div>
          <h2 className="text-center">Hourly Weather Forecast</h2>
          <div className="grid grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-7 gap-6">
            {forecast.forecastday.map((day, index) => (
              <div key={index} className="text-center rounded-lg flex flex-col items-center bg-green-950/25 p-10">
                <p>{new Date(day.date).toLocaleString("en-US", { weekday: "short" })}</p>
                {/* Check if `day.hour` is an array and not undefined */}
                {day.hour && Array.isArray(day.hour) && day.hour.map((hour, hourIndex) => (
                  <div key={hourIndex}>
                    <img
                      className="w-50 h-50"
                      src={hour.condition.icon}
                      alt={hour.condition.text}
                      aria-label={hour.condition.text}
                    />
                    <div>
                      <p className="bg-black/25 px-2 italic rounded-xl text-white mb-2">
                        High:{" "}
                        <span aria-label={`Maximum temperature: ${hour.temp_c.toFixed()} degrees Celsius`}>
                          {hour.maxtemp_c.toFixed()}°
                        </span>
                      </p>
                      <p className="bg-black/25 px-2 italic rounded-xl text-white">
                        Low:{" "}
                        <span aria-label={`Minimum temperature: ${hour.temp_c.toFixed()} degrees Celsius`}>
                          {hour.temp_c.toFixed()}°
                        </span>
                      </p>
                    </div>
                  </div>
                ))}
              </div>
            ))}
          </div>
        </div>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search