Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

95
Views
useEffect() without a cleanup function

it says that : "Each time that our component renders, our effect is called, adding another event listener. With just a few clicks and re-renders, we have attached a lot of event listeners to the DOM! We need to clean up after ourselves!".

so for every click the count goes from 1 to 3 to 7 instead of incrementing by 1. I don't understand how does so many event listeners got attached and how is this effecting the total count?

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

export default function Counter() {
  const [clickCount, setClickCount] = useState(0);

  const increment = () => {
    setClickCount(prev => prev + 1);
  };

  useEffect(() => {
    document.addEventListener('mousedown', increment);

  })

  return (
      <h1>Document Clicks: {clickCount}</h1>
  );
}

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

You're adding a listener to the document itself, so you need to remove it when component is unmounted.

And you need to add an empty dependency array to not add a new listener on each rerender

And you either need to wrap increment in a useCallback or use a different increment function in the useEffect:

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

export default function Counter() {
  const [clickCount, setClickCount] = useState(0);

  const increment = useCallback(() => {
    setClickCount(prev => prev + 1);
  }, [setClickCount]);

  useEffect(() => {
    document.addEventListener('mousedown', increment);

    return () => document.removeEventListener('mousedown', increment);
  }, [])

  return (
      <h1>Document Clicks: {clickCount}</h1>
  );
}
about 4 years ago · Juan Pablo Isaza Report

0

Without using an array of dependencies, every change will trigger your useEffect to run again.

So every re-render, every changing state will cause you to create another eventListener.

Let's talk about variant useEffect:

useEffect(() => {
  // invoking on every re-render
})
useEffect(() => {
  // invoking on component did mount (once)
}, [])
useEffect(() => {
  // invoking on component did mount and with every change on counter
}, [counter])

Also, you need to remove your eventLinstener on the component unmount:

 useEffect(() => {
    document.addEventListener('mousedown', increment);

    return () => document.removeEventListener('mousedown', increment);

  }, [])

Optional

As mentioned with Samathingamajig in the answers, you can use an optimized way to define your increment function with useCallback.

With the current implementation, your increment method will be re-defined every time (with every change and re-render) but using useCallback it will be redefined only when the useCallback's array of dependencies got changes.

import React, {useEffect, useCallback} from 'react';

// rest of the codes ...

  const increment = useCallback(() => {
    setClickCount(prevState => prevState + 1);
  }, [setClickCount]);
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!