Search code examples
javascriptreactjsreact-reduxmernredux-toolkit

abort() is not working in dependent UseEffect


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.


Solution

  • 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().