Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding React hooks useEffect function.When is the callback function(i.e unsubscribe) in useffect gets called?

I have been trying to understand when is unsubscribe(the callback in useEffect) gets called exactly.

This is the codepen link : https://codepen.io/deen_john/pen/eYmNdMy Code :

const { useState, useEffect } = React  ;
 
function App() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
    console.log("use effect called ");
    
    return () => {
      console.log("unsubscribe ")
    }
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Problem : In my example, the callback function in useEffect hook (i.e unsubscribe) , gets called every time i click on button (i.e every time i update the button state). But, as per the React documentation, callback in useEffect works like componentWillUnmount lifecycle , so in my example it should have been called only if the App component is unmounted. I am just updating the button state here,not unmounting App component on every click.

like image 263
Deen John Avatar asked Dec 05 '19 05:12

Deen John


People also ask

How do I call a callback function in useEffect?

The useEffect(callback, [prop, state]) invokes the callback after the changes are being committed to DOM and if and only if any value in the dependencies array [prop, state] has changed.

Where you would unsubscribe from subscription in useEffect?

This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. The instruction is pretty clear and straightforward, "cancel all subscriptions and asynchronous tasks in a useEffect cleanup function".

What happens when you return something inside a useEffect when does it get called?

The useEffect Hook is built in a way that we can return a function inside it and this return function is where the cleanup happens. The cleanup function prevents memory leaks and removes some unnecessary and unwanted behaviors.

When useEffect is called in React?

When you call useEffect , you're telling React to run your “effect” function after flushing changes to the DOM. Effects are declared inside the component so they have access to its props and state. By default, React runs the effects after every render — including the first render.


1 Answers

The unsubscribe event of useEffect is called everytime before the next call to useEffect as well as when the component unmounts

Since in your case, you haven't passed any dependency array to useEffect, your useEffect will run on each render of the component and hence the unsubscribe will run on each re-render before the next useEffect is triggered

A better way to write the above code would be to pass count in the dependency array to useEffect

const { useState, useEffect } = React;
 
function App() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
    console.log("use effect called ");
    
    return () => {
      console.log("unsubscribe ")
    }
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
like image 96
Shubham Khatri Avatar answered Sep 24 '22 21:09

Shubham Khatri