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
 
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
 
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
 
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
 
wintercounter profile image
Victor Vincent

Reading y is unnecessary in handleObserver.

Collapse
 
hunterjsbit profile image
Son Goku

Yes you are right

Collapse
 
saviomartin profile image
Savio Martin

Thank you!

Collapse
 
alfredosalzillo profile image
Alfredo Salzillo

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

Collapse
 
tombohub profile image
tombohub

why dont you have syntax highlighting?

Collapse
 
chisach profile image
Book

Thank you very much, brother

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
 
mathesouza profile image
Matheus Sabino

My handleObserver is being called twice with this code D:

Collapse
 
assouaalbert profile image
Al Baba

Easy steps to follow to create a user friendly Website