DEV Community

React infinite scroll in few lines

Son Goku on August 09, 2020

Introduction What is infinite scroll ? Infinite scrolling is a web-design technique that loads content continuously as the us...
Collapse
 
pacopacov profile image
PacoPacov • • Edited

Here is a cleaner version of the code above that compliance with Eslint.
There is a problem with the code . It'll add infinite number of elements without being triggered by scrolling to the end of the list.

import React, { useEffect, useState, useRef } from 'react'

const divStyle = {
  color: 'blue',
  height: '250px',
  textAlign: 'center',
  padding: '5px 10px',
  background: '#eee',
  marginTop: '15px',
}

const containerStyle = {
  maxWidth: '1280px',
  margin: '0 auto',
}

export function InfiniteScroll() {
  const [postList, setPostList] = useState({ list: [1, 2, 3, 4] })
  // tracking on which page we currently are
  const [page, setPage] = useState(1)
  // add loader reference
  const loader = useRef(null)
  // here we handle what happens when user scrolls to Load More div
  // in this case we just update page variable
  const handleObserver = (entities) => {
    const target = entities[0]
    if (target.isIntersecting) {
      setPage(_page => _page + 1)
    }
  }

  useEffect(() => {
    const options = {
      root: null,
      rootMargin: '20px',
      threshold: 1.0,
    }
    // initialize IntersectionObserver and attaching to Load More div
    const observer = new IntersectionObserver(handleObserver, options)
    if (loader.current) {
      observer.observe(loader.current)
    }
  }, [])

  useEffect(() => {
    // here we simulate adding new posts to List
    const newList = postList.list.concat([1, 1, 1, 1])
    setPostList({
      list: newList,
    })
  }, [page, postList.list])

  return (
    <div className="container" style={containerStyle}>
      <div className="post-list">
        {postList.list.map((post, index) => (
          <div key={index} className="post" style={divStyle}>
            <h2>{post}</h2>
          </div>
        ))}
        <div className="loading" ref={loader}>
          <h2>Load More</h2>
        </div>
      </div>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
raibtoffoletto profile image
Raí B. Toffoletto •

Be carefull... that postList.list as dependencies will make your component enter an infinite loop of rerenders. It is better to access this property via an arrow function.

  useEffect(() => {
    setPostList((x) => ({
      list: x.concat([1, 1, 1, 1]),
    }))
  }, [page])
Enter fullscreen mode Exit fullscreen mode

Also, handleObserver is better to be insde the useEffect function and you should clear (observer.unobserve) the listener on a callback funtion. ;)

Collapse
 
momin profile image
Md Abdul Momin •

You wrote ContactPage function and export InfiniteScroll ! Should review the code and fix

Collapse
 
ipoool profile image
Asep saepulloh •

haha yes, I think he has tried to copy-paste and forget to change the name of function 😁

Collapse
 
hunterjsbit profile image
Son Goku •

Updated thank you, Yup you are right left over while copying from VS code :D

Collapse
 
leomjaques profile image
leo 👨🏻‍💻 •

Nice, Kakarot. I will for sure try it out ✨

Collapse
 
hunterjsbit profile image
Son Goku •

Thank you for reading, and yes please go try it out :)

Collapse
 
benupham profile image
benupham •

How would I turn off this observer when certain conditions are met, for example if some state changes (ie, I make it to the last set of items/last page)? I've tried observer.disconnect inside the useEffect hook, but it does not seem to work.

Collapse
 
andrewbaisden profile image
Andrew Baisden •

Thanks good article I will try this out.

Collapse
 
mathesouza profile image
Matheus Sabino •

My handleObserver is being called twice with this code D:

Collapse
 
wintercounter profile image
wintercounter •

Reading y is unnecessary in handleObserver.

Collapse
 
hunterjsbit profile image
Son Goku •

Yes you are right

Collapse
 
deepakfilth profile image
deepak pd •

Failed to compile due to 'IntersectionObserver' is not defined no-undef.
Has anyone faced such issue?

Collapse
 
hunterjsbit profile image
Son Goku •

Hmm you should not have that issue, you can check how intersectionObserver is used here:developer.mozilla.org/en-US/docs/W...

Collapse
 
deepakfilth profile image
deepak pd • • Edited

It is now working with windows.IntersectionObserver

Collapse
 
chisach profile image
Book •

Thank you very much, brother

Collapse
 
tombohub profile image
tombohub •

why dont you have syntax highlighting?

Collapse
 
alfredosalzillo profile image
Alfredo Salzillo •

Nice article! But please add the javascript tag to the code-blocks for syntax highlights

Collapse
 
saviomartin profile image
Savio Martin •

Thank you!

Collapse
 
assouaalbert profile image
Al Baba •

Easy steps to follow to create a user friendly Website