Why is set state in my useEffect causing the component to mount?

Viewed 43

I have a React component that needs to setup a receiver when mounted, and that receiver needs to read a state value, and then set it to a new value. However this is causing the component to mount again (loosing the state values), also interestingly it seems unmount is not fired when this happens.

If i just read the state value it is fine, or if I just write to the state value it is fine, but it seems I can't read it and then write to it in the useEffect? What is the proper way to go about this?

const [currentData, setCurrentData] = useState(null);

  // On Mount
  useEffect(() => {
    console.log("mount dataLoaded")
      window.api.receive("dataLoaded", (data) => {
        console.log(currentData)
        setCurrentData({})
    })
  }, [currentData]);

  // on Unmount
  useEffect( () => () => {
    console.log("unmount dataLoaded")
    window.api.removeListeners("dataLoaded")
  }, [] );
2 Answers

You can use a single useEffect() statement and return a cleanup function when you want to perform an action during the unmount.


useEffect(() => {
   //do something here

   return () => {
      //here clean whatever you want. remove listeners etc.
   }
}, [])

The way you do it now, is like having two effects that run both on mount with the only difference that the first has a dependency while the second doesn't. Essentially, you add and remove the listener at "almost" the same time

The issue was with my understanding of useEffect, I understood it to be a direct replacement for "componentDidMount". Parsing in a value in the dependency array will cause the useEffect to run every time that value changes. In my case every time "currentData" changed it would run the effect.

What I needed was to have the useEffect setup my listener (window.api.receive) only once when the component was loaded but within the listener function use the current value of 'currentData' rather than the value that was current when the component was loaded. I had to change my react component to a class and use componentDidMount() to achieve this.

Related