skip to Main Content

Attempting to dynamically render weather information from an API. API request is returning data that I can display in the log and on the page. However, when I attempt to display individual items in my responses arrays, the web console reports that it cannot read properties of undefined (reading ‘0’). The whole page will then stop rendering.

Code

<script>
import axios from 'axios'

export default{
  data() {
    return {
      weather: []
    };
  },
  async created(){
    try{
      const response = await axios.get('apilinkredacted');
      this.weather = response.data.daily;
      console.log(this.weather)
    } catch (error) {
      console.error(error);
    }
  }
}
</script>

<template>
  <main>
    <div v-for="n in 4" class="text-cliPurple border-t border-windowOutline pb-2 pl-2">

      <!-- weather.daily.temperature_2m_max[n-1] -->
      <p class="underline">{{ weather.time[n-1] }}</p>

    <div class="grid grid-cols-2">
      <div class="">
        <pre>
        /
      .-.
   ― (   ) ―
      `-’
     /   
        </pre>
      </div>
      <div class="text-left">
        <p><span class="text-cliOrange">Temp:</span> {{ weather.temperature_2m_max[n-1] }} C</p>
        <p><span class="text-titleColor">Rain Chance:</span> {{ weather.precipitation_probability_max[n-1] }}%</p>
        <p><span class="text-userColor">Rain Amount:</span> {{ weather.rain_sum[n-1] }}mm</p>
        <p><span class="text-cliRed">UV:</span> {{ weather.uv_index_max[n-1] }}</p>

      </div>
    </div>
  </div>
  </main>
</template>

JSON response

{
    "latitude": -35.25,
    "longitude": 149.125,
    "generationtime_ms": 0.06699562072753906,
    "utc_offset_seconds": 36000,
    "timezone": "Australia/Sydney",
    "timezone_abbreviation": "AEST",
    "elevation": 568,
    "daily_units": {
        "time": "iso8601",
        "temperature_2m_max": "°C",
        "apparent_temperature_max": "°C",
        "uv_index_max": "",
        "rain_sum": "mm",
        "precipitation_probability_max": "%"
    },
    "daily": {
        "time": [
            "2024-05-09",
            "2024-05-10",
            "2024-05-11",
            "2024-05-12",
            "2024-05-13",
            "2024-05-14",
            "2024-05-15"
        ],
        "temperature_2m_max": [
            16.5,
            14.9,
            13.1,
            13.4,
            17.5,
            15.9,
            14.7
        ],
        "apparent_temperature_max": [
            14.4,
            13.2,
            11.4,
            11.1,
            16,
            14.6,
            13.8
        ],
        "uv_index_max": [
            1.95,
            2.55,
            0.6,
            3.9,
            4.2,
            3.95,
            3.65
        ],
        "rain_sum": [
            0,
            5.1,
            26.5,
            3.7,
            0,
            0,
            0
        ],
        "precipitation_probability_max": [
            52,
            74,
            90,
            37,
            0,
            0,
            3
        ]
    }
}

I initially thought it was because the item wasnt an array but when I used console.log(this.weather.time[0]) I get the correct data printed in the web console. If I don’t specify the specific items, I can render the whole response multiple times but when I add the specifics and reload the entire page goes blank.

Additionally, when I the Get request to store the individual array this.weather = response.data.daily.time; I can address the individual items by using weather[0] and it displays no problem.

2

Answers


  1. Chosen as BEST ANSWER

    Daniel was correct, page was rendering before the get request had been fulfilled. Changed the weather type to {} and added this around the v-for:

    <div v-if="weather.time">
    

    Now it waits until the request has data to attempt rendering the component.


  2. You are trying to access data that does not yet exist.
    You have two options

    1. use ? (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining)

      {{time?.time[n-1] }}

    2), introduce a v-if in your code

        <template>
          <main v-if="Object.keys(weather).length>0">
            <div v-for=‘n in 4’ class=‘text-cliPurple border-t border-windowOutline pb-2 pl-2’>
        ...
    

    On the other hand, you are making some mistakes.
    The first is that the weather data type is a [], but then you pass a {} when you set it in the created method.
    The second is that you should avoid accessing data by index

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search