Gilberto S. Rocha
Gilberto S. Rocha

Reputation: 167

Can't understand why async/await isn't working NextJs

I'm looking for a help with how to make a chunk load, when the user scrollbar, and reach a specific div, then it shoul run a function one time, but the code run multiples time:

async function loadMore(){
       console.log('i load more');      
 }

window.addEventListener('scroll', async (event) => {
        const {
            scrollTop,
            scrollHeight,
            clientHeight
        } = document.documentElement;
    
        if (scrollTop + clientHeight >= scrollHeight - 1 ) {            
            document.getElementById('final').style.height = '3000px'
            let msg = await loadMore() 
            console.log('i finish') 
            document.getElementById('final').style.height = '30px'      
        }
        
    }, {
        passive: true
    });

return (
        <div id='final'>
            <Image src="/ajax-loader.gif" width={60} height={60} alt="loader spinner"></Image>
        </div> 
    )

Upvotes: 0

Views: 953

Answers (2)

vighnesh153
vighnesh153

Reputation: 5416

Few things:

  • You should add the window event listener in a useEffect.
    • If you add the event listener in the render phase of the component, it will run add a event listener on every render which might be 1 of the reasons why it is running multiple times.
    • You also need to cleanup the event listener as a cleanup of useEffect else you will again end up with a lot of event listeners
  • You need to debounce the onScroll handler
    • Scroll event is triggered several times when you scroll which is something you might not want. So, adding a debounce will help reduce the number of times, the handler is called when a user scrolls.
    • Lodash's debounce is 1 popular implementation of debounce. You can choose other implementations if you want or create your own one.
import debounce from "lodash.debounce";

function YourComponent() {
  async function loadMore(){
    console.log('i load more');      
  }
  
  // "useEffect" so that you don't add a new event listener 
  // on every render
  useEffect(() => {
    const onScroll = async (event) => {
      // Whatever you want to do when user scrolls
    }
    
    // This is the debounced "onScroll" function instance
    // "500" specifies that it will be debounced for 500 milliseconds 
    const debouncedOnScroll = debounce(onScroll, 500);

    // Attach the event listener to window
    window.addEventListener('scroll', debouncedOnScroll);

    // Cleanup the event listener when component unmounts or 
    // when the "useEffect" runs again.
    return () => window.removeEventListener('scroll', debouncedOnScroll);
  }, []);


  return (
    <div id='final'>
      {/* Rest of your JSX */}
    </div> 
  )
}

Upvotes: 1

Latiful Mousom
Latiful Mousom

Reputation: 11

trigger window event listener inside useEffect

make sure to cleanup the event: return () => window.removeEventListener('scroll', callback);

Upvotes: 0

Related Questions