Home > database >  abort() is not working in dependent UseEffect
abort() is not working in dependent UseEffect

Time:01-21

I am trying to optimize my react code by fixing any memory leaks. I am using createAsyncThunk canceling-while-running to cancel requests, if my component unmounts.

I have three reducers inside two useEffect hooks. One dispatches when the component mounts and the other two dispatches when the response from the first dispatched reducer arrives.

Below is my code:

useEffect(() => {
  const promise = dispatch(bookDetails(bookId))
  return () => promise.abort()
}, [])

// this is triggered when the response from the dispatched "bookDetails" reducer arrives
// and get stored in the "book" variable as shown in dependency array
useEffect(() => {
  let promise1, promise2
  if (book._id !== undefined) {
    promise1 = dispatch(getComments(book._id))
    promise2 = dispatch(relatedBooks({ genre: book.genre }))
  }
  return () => {
    promise1.abort() // BookDetails.jsx:58:1
    promise2.abort()
  }
}, [book])

When the component mounts the second useEffect gives me an error, given below:

BookDetails.jsx:58 Uncaught TypeError: Cannot read properties of undefined (reading 'abort')
    at BookDetails.jsx:58:1
    at safelyCallDestroy (react-dom.development.js:22932:1)
    at commitHookEffectListUnmount (react-dom.development.js:23100:1)
    at invokePassiveEffectUnmountInDEV (react-dom.development.js:25207:1)
    at invokeEffectsInDev (react-dom.development.js:27351:1)
    at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27324:1)
    at flushPassiveEffectsImpl (react-dom.development.js:27056:1)
    at flushPassiveEffects (react-dom.development.js:26984:1)
    at performSyncWorkOnRoot (react-dom.development.js:26076:1)
    at flushSyncCallbacks (react-dom.development.js:12042:1)

I tried few things but it didn't workout for me.

CodePudding user response:

Since the promise1 and promise2 is assigned within the condition book._id !== undefined , it has the possibility of not being assigned. Simple quick fix is checking a condition when invoking .abort(). Something like promise?.abort() or typeof promise?.abort === 'function' && promise.abort().

CodePudding user response:

There is a condition on dispatching the asynchronous actions in the second useEffect hook. This means that promise1 and promise2 are potentially undefined. Only return the cleanup function if the actions are dispatched.

Example:

useEffect(() => {
  if (book._id && book.genre) {
    const promise1 = dispatch(getComments(book._id));
    const promise2 = dispatch(relatedBooks({ genre: book.genre }));

    return () => {
      promise1.abort();
      promise2.abort();
    };
  }
}, [book]);
  • Related