As mentioned in the article provided, we have to understand three things:
- HTML that contains the images and a loading indicator
- a CSS file that controls the animation of loading indicator and how big the images are
Scroll down to the bottom and you will see .loading and .loading.show CSS rule. This is the part where if the div holding the loading indicator has a subclass of show(added when the user scrolls to the bottom of the page), the loading icons show up.
With react, we no longer need to use opacity, and instead, we can jsx to conditionally display the loading indicator.
React allow us to modularize a lot of our code and what that means is we can also modularize the loading indicator as well as the photo gallery.
Base on that, we can divide our code into the following:
- photo gallery component
- loading indicator component
Technically, we can separate js and CSS files into one used for photo gallery and loading indicator. However, we can accidentally mix up CSS rules if there are CSS rules from the photo gallery component and loading indicator component named the same.
What will happen is one CSS rule overwrites another and that’s why I kept everything into one HTML, one js, and one CSS file only.
To start, you need to run npx create-react-project infinite-gallery.
Afterward, under the src folder create a components folder and create a PhotoGallery.js:
Let’s break down into chunks that we can understand. In our constructor, we set our initial state to have a placeholder for a list of photos, the current page to fetch photos from, and as well as a loading boolean. This boolean helps us determine whether to show the loading indicator or not. The boolean only gets shifted to true only when the user scrolls to the bottom of the page.
Also within the constructor, we added an onscroll event listener. We get scrollTop, clientHeight, and scrollHeight, which is used to determine whether or not we are on the bottom of the page:
If we are on the bottom of the page, the loading state of the photo gallery gets set to true, effectively rendering the loading indicator. Afterward, we increment the page count so on our API call we will be getting different images every time.
After we retrieve the images, we add our images on top of the ones we have and set the loading state to false. On top of all this, we wrap the API call and setState in a debounce function. What this will do is wait for 1000 ms(can be as long as you want) before the API gets called. This is to prevent excessive API calls to be made to get images since the user can be scrolling to the bottom of the page again before the new images are retrieved.
How about when we initially load the page? That’s where componentDidMount comes in. With the componentDidMount lifecycle method, we can get photos and populate the page before the page is even rendered.
Once the page renders, we populate the photos we have and if the loading state is turned on, then the loading indicator will show up.
We talked enough about how the photo gallery. How about the loading indicator? How does that look?
Under the src/components folder, create a PhotoGallery.js with the following contents:
However, we need to wrap the keyframes into global CSS in order for other CSS rules that use the animation key-frames to understand what they are.
Within the ball CSS, we set its width and height as well as the nature and the duration of the animation. AnimationTimingFunction determines the nature, animationDuration determines how long it will take, and animationIteration determines how frequently the animation occurs.
With react, you don’t need to worry about any of this! All you have to worry about is figuring the right lifecycle method to use and make the API call to dump the data into the local state. If the data is not ready, all you need is to set the loading state variable to true and show a loading indicator! That’s it! You don’t have to worry about using jquery to attach data to a specific node in the dom.
That’s it! Happy coding!