Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

React useEffect hooks return () => cleanup() vs return cleanup

I have a question about useEffect‘s cleanup callback function. In one word, return cleanup gives an error, but return () => cleanup() works well. Yes, they are different, but how are they different? Does anyone know how to explain? Thanks,

I came across this question while I am writing with codemirror.

An error message is

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Unhandled Runtime Error
TypeError: Cannot read properties of undefined (reading 'plugins')

My hooks

export const useCodeMirror = () => {
  const state = ...
  const parent = ...
  
  useEffect(() => {
    const view = new EditorView({state: state, parent: parent})
    // return view.destroy raises an error
    return () => view.destroy()  // works perfectly
  }, [element])
}

node_modules/@codemirror/view/dist/index.js L:6740-6750

    destroy() {
        for (let plugin of this.plugins)
            plugin.destroy(this);
        this.plugins = [];
        this.inputState.destroy();
        this.dom.remove();
        this.observer.destroy();
        if (this.measureScheduled > -1)
            cancelAnimationFrame(this.measureScheduled);
        this.destroyed = true;
    }

package.json

{
  "dependencies": {
    ...
    "codemirror": "^6.0.1",
    ...
  }
}

>Solution :

It’s normally fine to return a cleanup function directly, rather than wrapping it in an additional arrow function. The only reason the additional function is needed in this case because destroy uses this.

For regular functions, the value of this is determined by how the function is called. So if you have code that says view.destroy(), then the characters view. are the reason that this gets set to view. That’s why () => view.destroy() one works: you are explicitly saying what this should be, as you call the function.

But if you just return view.destroy, you are not calling the function, just returning a reference of it to react. React doesn’t know anything about view, it just knows you returned a function. So when react later calls your function, it doesn’t know what to set this to, and so this gets set to undefined. Since it’s undefined, this.plugins causes the error you see.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading