0
votes

I'm a new student of Computer Science and I have a school project to do on Vue.js. It is working, but it shows the following Warning:

[Vue warn]: You may have an infinite update loop in a component render function.

English is not my first language, so I'm sorry if I write anything wrong in advance, but I'll try to explain what I have to do on the project.

I have to create a Photo Grid/Album that shows no more than 3 photos on each line. Something like this: Example of how it has to look

The code is like this:

  <template>
<v-container>
  <!-- 'v-container' est´substituindo ' div class="clubes-lista" '-->
  <div class="grid-photo">
    <v-container class="grey lighten-3">
      <v-row
        v-for="index in numberLines()"
        :key="index"
        class="grey lighten-3"
      >
        <v-col v-for="n in 3" :key="n" cols="4">
          <v-card v-if="numberPhotos > checkInsertedAllPhotos()" outlined>
            <v-img
              src="https://i.pinimg.com/736x/96/28/b7/9628b7892fd0543782f53eeec4bae502.jpg"
              alt="Bird Photo"
            >
            </v-img>
            <div class="photo-subtitle">
              <v-icon size="15">mdi-heart-outline</v-icon>
              <p>The Cockatiel</p>
            </div>
          </v-card>
          <v-card v-else></v-card>
        </v-col>
      </v-row>
    </v-container>
  </div>
</v-container>
<script>
export default {
name: "PhotoGrid",

data() {
  return {
    listPhotosOnGrid: [],
    numberPhotos: 0,
    numberTotalLines: 0,
    countPhotos: 0,
  };
},

computed: {},

methods: {
  createPhotosList() {
    var listPhotos = [];
    for (var i = 0; i < 10; i++) {
      var aux = {
        id: i + 1,
        src:
          "https://i.pinimg.com/736x/96/28/b7/9628b7892fd0543782f53eeec4bae502.jpg",
        subtitle: "The cockatiel",
      };

      listPhotos.push(aux);
    }

    this.listPhotosOnGrid = listPhotos;
    this.numberPhotos = listPhotos.length;
  },

  numberLines() {
    this.createPhotosList();
    var photosMultipleThree = this.numberPhotos;

    while (photosMultipleThree % 3 != 0) {
      photosMultipleThree = photosMultipleThree + 1;
    }
    this.numberTotalLines = photosMultipleThree / 3;

    return photosMultipleThree / 3;
  },

  checkInsertedAllPhotos() {
    var cont = this.countPhotos++;
    return cont;
  },
},

};

<style scoped>
.photo-subtitle {
  font-size: 10px;
  display: flex;
  flex-direction: row;
  justify-content: left;
  align-items: flex-start;
  padding: 0;
  margin-top: 10px;
}

.photo-subtitle p {
  margin-left: 5px;
}

So... Trying to figure out what is happening, I think the Warning comes from the following line:

<v-card v-if="numberPhotos > checkInsertedAllPhotos()" outlined>

The if is because it can't show more images that what is given. For example, each line shows 3 photos, so if I don't have a total of photos that is multiple os 3, I don't want to fill all columns on the last line, only the necessary to show all the photos.

But I just think, based on some tests, I'm not sure if the Warning comes from this line.

The code works, but I feel something is not right. (It works partialy actually, because I still don't know how to get the info from the array to show, so it only loops the same thing)

I want to learn how to make it right.

So does anyone can tell me what I can do to make the Warning disappear or if I have to change everything, and make make a new logic for it to work properly.

I just want to learn.

Thank you so, so much and sorry again if this is a stupid question, or if I'm making everything wrong, hehe. And sorry if I wrote anything wrong.

:)

2
First of all, 1. this function checkInsertedAllPhotos() always return 1 because you only increment 1 once. 2. v-for="index in numberLines()" The numberLines() here is a number, because you return photosMultipleThree / 3. You can't loop through a number.KienHT
3. It's not recommended to use v-if inside v-for. Instead, using computed properties to filtered the array first, then loop through the filtered arrayKienHT

2 Answers

0
votes

I've had a look to your code. First I would recommend you to stop using the var keyword but use let or const instead (you may check the question here and have a look at the scope based on those keyword, the var scope is very unusual nowadays and it will lead you to some issues).

Regarding your particular issue of infinite update loop, the problem comes from your checkInsertedAllPhotos function. I would explain it like this :

  • In the v-if Vue internal mechanisms checks if the element should be rendered by triggering the function checkInsertedAllPhotos

  • When executing the function checkInsertedAllPhotos the data countPhotos is increased (by the way it would be better to just do

    this.countPhotos ++; return this.countPhotos;

  • Since the Data has been modified Vue is triggering a re-render of the page

  • Since there is a re-render Vue checks in the v-if if the element should be rendered by triggering the function checkInsertedAllPhotos.

And it could be infinite if Vue doesn't prevent it !

I would suggest to re-work a little bit your logic indeed. However a quick solution for your problem would be that when you're checking an index in your list : for example if you want to display listPhotosOnGrid[i], you check if i<numberPhotos with a v-if and in the v-else you can display something else if you want.

I also think you could have a much simpler code, by leveraging css (for example css-grid). You can have something as simple as this :

<div v-for="n in 100">
    <img v-bind:src="`https://i.pinimg.com/photos/${n}.png`">
</div>

and some css to style it and only have 3 items per rows. If you want to learn about css-grid I would recommend Mozzila documentation or the following tutoriel.

Right now I have a little trouble understanding the exact question, since there are multiples topics inside to solve but I hope my explanation on the infinite loop will help you !

Have fun while learning Vue !

0
votes

Thank you everyone who helped me, and you sure helped me!!!!

I'm sorry I could only anwser today. I think I was able to do much better on the code, I changed it a lot, specially the logic on the code. And I think it can get even better, but for sure I already made a big progress, hehe.

I was a bit reluctant of posting this question because even though that as the time that I posted it I wasn't sure of what to do, I kinda of had the feeling that was something stupid (like a stuid question), and that I would only be taking the time of anyone who stopped by my question. But I only got amazing answers, with everyone being so patient, so THANK YOU SO, SO MUCH!!

(I'm also new to StackOverflow, so I hope I'm making everything right, hehe)