node.jsjsonvue.jsaxiosv-for

Vue Cannot read properties of undefined (reading '0')


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.


Solution

  • 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