skip to Main Content

I’m working with Vue 3.
If I write this:

<p v-for="(prs, index) in settings.pressure">{{settings.pressure[0].value}}</p>

I see the value correctly, while if I use this (the one I need):

<p>{{settings.pressure[0].value}}</p>

it throws an error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘0’)

How could it be defined in the first version and undefined in the second?

2

Answers


  1. It seems that settings.pressure is undefined when the template is loaded.

    You are able to for in loop an undefined element without throwing an error. Since it does not loop over anything, <p>{{settings.pressure?.[0].value}}</p> will not be evaluated. As such it gives time for your settings.pressure state to be loaded which will render the element as expected.

    The code below will print "No error thrown"

    try {
        for (let i in undefined) {}
        console.log("No error thrown")
    } catch (error) {
        console.log("Error thrown")
    }
    

    Your second answer however, immediately access’s the first element of the array which is undefined. This will throw the error you have.

    You may want to try using an optional so that an error is not thrown until the state is loaded.

    <p>{{settings.pressure?.[0].value}}</p>

    Login or Signup to reply.
  2. Brief explanation: settings.pressure is empty when component is mounted and gets populated shortly after. Therefore, when running the code outside of v-for it errors because settings.pressure is undefined. (It would fail similarly if settings.pressure[0] was undefined). But when settings.pressure gets populated, the v-for is run and at that time the code no longer errors, because settings.pressure[0] is no longer undefined. It’s the first element in settings.pressure.


    The template code of the v-for directive (no matter what that code does), gets executed once for each item in the collection 1 being iterated.

    So when settings.pressure is empty or falsey ([], {}, new Set(), new Map(), null, undefined, 0, NaN, false), it runs the template code once for each item in the collection: 0 times!

    When you run settings.pressure[0].value outside of v-for, if settings.pressure is null or undefined, JS will complain it can’t find property 0 of null or undefined. If you initially used an empty array/object/map/set, the code would try to find the first item in settings.pressure (which would be undefined). And then it would error when attempting to access value of undefined.

    Whenever you try to access any property of null or undefined, JavaScript will throw an error telling you they don’t have any properties (because they can’t have properties, by design) and therefore they can’t be queried for properties.

    Important side-note: if settings.pressure[0], when populated, is a ref(), you don’t need .value in <template />. All refs are unwrapped by Vue automatically in template (which means you don’t .value, like inside <script />).


    1 – typically we use arrays with v-for, but it can also iterate over an object’s properties, over JavaScript Maps and Sets and you can also pass a plain number to it (n) and it will run the template code n times.

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