skip to Main Content

I have a list of women on a page. I have a component for each woman. If I click on a woman I want to show the component for that woman. If I click on another woman I want to show that component as well. So there can be any number of components loaded at one time.

It works and I see three different components for each woman but if I place a condition on the component then nothing shows and I get an error:

Property "index" was accessed during render but is not defined on instance.

But isn’t it defined in the component?

Here is my complete code for the page:

<template>
  <div class="page" id="womensPage">
    <div>
      <Contestant
        v-for="(woman, index) in women"
        :key="index"
        :contestant="woman"
        v-if="activeWindows.includes(index)"
      />
    </div>
    <div class="pageContent">
      <h1 class="center fs26 fw800 red uc mb50">Females</h1>
      <div class="contestantListWrap">
        <div class="womenList flex between">
          <div class="woman mb10" v-for="(woman, index) in women" :key="index" @click="loadWoman(index)">
            <img :src="woman.picture" class="womanImg" />
            <h3 class="flex red jCenter">{{ woman.firstName }} {{ woman.lastName }}</h3>
            <p>Age {{ woman.age }}</p>
            <p>Country: {{ woman.country }}</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
// imports
import { ref } from "vue";
import Contestant from "@/components/Contestant.vue";

const activeWindows = ref([]);

const women = ref([
  {
    id: 1,
    picture: "/src/assets/img/one.jpg",
    firstName: "Alice",
    lastName: "Smith",
    age: 30,
    country: "USA",
  },
  {
    id: 2,
    picture: "/src/assets/img/two.jpg",
    firstName: "Maria",
    lastName: "Garcia",
    age: 25,
    country: "Spain",
  },
  {
    id: 3,
    picture: "/src/assets/img/three.jpg",
    firstName: "Yuki",
    lastName: "Tanaka",
    age: 28,
    country: "Japan",
  },
]);

// state

const loadWoman = (id) => {
  activeWindows.value.push(id);
};
</script>

2

Answers


  1. It appears that the problem you’re encountering stems from how you’re using the v-if directive in your v-for loop. The Property "index" was accessed during render but is not defined on instance error is typically caused by a scoping issue where Vue tries to evaluate something that isn’t correctly defined in the context it’s being accessed.

    In your setup, you are using index to manage the visibility of the Contestant components with activeWindows.includes(index). If activeWindows contains the index, the component should show. Here’s what might be causing your issue and how you can fix it:

    Recommended Fix

    1. Separate v-if from v-for: To ensure Vue can correctly track the list and the condition, use a template tag to wrap your Contestant component and place the v-if on this template tag:

      <template v-for="(woman, index) in women">
        <Contestant
          v-if="activeWindows.includes(index)"
          :key="index"
          :contestant="woman"
        />
      </template>
      
    2. Manage State with IDs instead of indices: Using array indices in activeWindows can lead to bugs when the order of items in your array changes or items are added/removed. It would be better to use unique identifiers (like woman.id), which are stable regardless of the order:

      const loadWoman = (id) => {
        if (!activeWindows.value.includes(id)) {
          activeWindows.value.push(id);
        } else {
          // Optionally, remove the woman from activeWindows if already present
          activeWindows.value = activeWindows.value.filter(wid => wid !== id);
        }
      };
      

      And in your template, check for active IDs instead of indices:

      <template v-for="(woman, index) in women" :key="index">
        <Contestant
          v-if="activeWindows.includes(woman.id)"
          :key="woman.id"
          :contestant="woman"
        />
      </template>
      

    This adjustment not only resolves potential errors with index tracking but also makes your component management more robust to changes in the data structure.

    Login or Signup to reply.
  2. Vue SFC Playground

    Alternatively, you can filter the array on the fly:

    <Contestant
      v-for="woman in womens.filter(el => activeWindows.includes(el.id) )"
      :key="woman.id"
      :contestant="woman"
    />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search