1

I am working on SSR React-based application using NextJS. Once DOM has been rendered I need to detect a set of elements visibility in the viewport and once they are visible I need to do something. Now to accomplish that I need the reference to that set of elements which I am taking in componentDidMount lifecycle method, having an understanding that since DOM has been completely rendered I can grab all the elements together and watch them if they are in the viewport or not.

Below code is for taking the reference of the set of elements:

componentDidMount() {

    this.imageContainer = document.getElementsByClassName("prod_images");
    console.log('imageContainer -> ', this.imageContainer, 'length ->', 
    this.imageContainer.length, 'type is -> ', typeof this.imageContainer);
}

So, I get an HTMLCollection of a set of images which are stored in imageContainer variable. I did a console below and I get below in console :

enter image description here

In the above SS, I have only shown 4 entries from HTML Collection object, but I get all 141 correctly. My problem is that I am getting this.imageContainer.length as 0 in console, though the values are present. I use this.imageContainer.length, later on, to loop through the elements and at that time the value is 0.

Link -> Javascript HTML collection showing as 0 length explains the fact that this might be due to DOM elements are not loaded by that time and we should do this check in DOMContentLoaded. But I am already using componentDidMount lifecycle method. So what is the issue and why length is coming as 0. Is it got to do something with SSR?

Shantanu Tomar
  • 1,572
  • 7
  • 38
  • 64
  • Because whatever is adding those elements is doing it after you read them. `getElementsByClassName` is a live Html Collection so as you add/remove things, it updates. That little [i] icon in the console is telling you it is updated. – epascarello Mar 09 '20 at 13:22
  • Okay. I got it. It also says that value is just computed. What should be the right way to get the length or value of all the elements. – Shantanu Tomar Mar 09 '20 at 13:41
  • Why do you need to use `getElementsByClassName` is react? What exactly are you trying to do? – epascarello Mar 09 '20 at 13:45
  • Need to achieve lazy loading of images on scroll. Once dom has been rendered, get reference of images and check if they are in viewport. If they are, set it's src attribute. Its working fine lazy load part in scroll. Its just that on initial render and not on scroll, if images are in viewport need to check elements visibility. For that need to loop through the values. – Shantanu Tomar Mar 09 '20 at 13:55
  • https://stackoverflow.com/questions/26556436/react-after-render-code – epascarello Mar 09 '20 at 13:58
  • But I am already using componentdidmount. I am taking the ref inside that lifecycle hook only – Shantanu Tomar Mar 09 '20 at 14:08
  • Look at the second answer – epascarello Mar 09 '20 at 14:12

1 Answers1

-1

As suggested in comment by epascarello

Because whatever is adding those elements is doing it after you read them. getElementsByClassName is a live Html Collection so as you add/remove things, it updates. That little [i] icon in the console is telling you it is updated

This is the right answer and solved my problem

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • you should post this as a comment – phoenixstudio Jan 02 '21 at 11:13
  • @phoenixstudio seems like this was originally a [comment](https://stackoverflow.com/questions/60601380/html-collection-length-is-0-even-after-dom-has-been-rendered/65538033#comment107213594_60601380) that OP is trying to convert to answer... – Suraj Rao Jan 02 '21 at 11:29