Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Cannot read property 'body' of null #15691

Closed
aralroca opened this issue May 21, 2019 · 20 comments
Closed

TypeError: Cannot read property 'body' of null #15691

aralroca opened this issue May 21, 2019 · 20 comments

Comments

@aralroca
Copy link

aralroca commented May 21, 2019

This method:

https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/client/getActiveElement.js

Is throwing this error in jest:

image

I realize that this method is checking only when the document is undefined. However, using jest looks that is setting sometimes the document to null, causing this error.

To reproduce it, I'm testing a callback that is using an async task:

 const asyncTask = useCallback(async (data) => {
    dispatch({ type: 'FETCH' })

    try {
      const res = await MyService.asyncMethod(data)
      dispatch({ type: 'SUCCESS', data: res })
    } catch (e) {
      dispatch({ type: 'ERROR' }) // This dispatch throw this error in jest
    }
  }, [])

About the test, I'm just mocking the service and testing the different scenarios.

I imagine that is related that the dispatch from the useReducer, that it's used inside the catch, is fired when the component maybe is unmount? @gaearon In this case how can I do a safer dispatch inside a callback method?

@aralroca
Copy link
Author

I tried to do this:

 const dispatchSafe = useSafeDispatch(dispatch)

 const asyncTask = useCallback(async (data) => {
    dispatchSafe({ type: 'FETCH' })

    try {
      const res = await MyService.asyncMethod(data)
      dispatchSafe({ type: 'SUCCESS', data: res })
    } catch (e) {
      dispatchSafe({ type: 'ERROR' }) // This dispatchSafe throw the error in jest
    }
  }, [])

When useSafeDispatch is:

export default function useSafeDispatch(dispatch) {
  const dispatchSafe = useRef(dispatch)

  useEffect(() => () => {
    dispatchSafe.current = () => null
  }, [])

  return dispatchSafe.current
}

However, this doesn't solve the problem. Maybe I'm doing something wrong?

@threepointone
Copy link
Contributor

could you make a repro with codesandbox, or a git repo? can't say without more info.

@cristiam86
Copy link

I'm also having this issue. In my case it only happens when there is a console.log inside the catch.

No error:

async componentDidMount() {
  try {
    const helpMenu = await MenuService.getMenuAyuda();
    this.setState({ helpMenuArray: helpMenu });
  } catch (error) {}
}

Error:

async componentDidMount() {
  try {
    const helpMenu = await MenuService.getMenuAyuda();
    this.setState({ helpMenuArray: helpMenu });
  } catch (error) { console.log(error) }
}

@Avd6977
Copy link

Avd6977 commented Jul 29, 2019

Also seeing this issue. Pretty much the same try catch as @cristiam86

@ishristov
Copy link

ishristov commented Jul 31, 2019

I'm also seeing the same error "TypeError: Cannot read property 'body' of null".
Would changing if (typeof doc === 'undefined') in https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/client/getActiveElement.js to if (doc == null) make sense?

@threepointone
Copy link
Contributor

threepointone commented Jul 31, 2019

Please share a codesandbox repro, or even a link to a git repo that reproduces this problem.

ishristov added a commit to ishristov/react that referenced this issue Jul 31, 2019
During tests (with react-testing-library) a test randomly fail
with "TypeError: Cannot read property 'body' of null" in the getActiveElement.
It appears that sometimes the document is null but the check in the file only
checks for undefined. This proposed change checks for both null or undefined
which should prevent the failures.

facebook#15691
@rzane
Copy link

rzane commented Jul 31, 2019

I also encountered this issue today. It looks like global.document is being set to null when Jest's JSDOM environment is being torn down:
https://github.com/facebook/jest/blob/72c920e4f8feff5f2b319c4111da8c989de54995/packages/jest-environment-jsdom/src/index.ts#L109

Since getActiveElement never checks for null, we're seeing this error.

This might just be a problem with my test though, because it seems that getActiveElement is being invoked after Jest thinks the test finished.

@gaearon
Copy link
Collaborator

gaearon commented Jul 31, 2019

Can anybody provide a reproducing case please? :-) That's the fastest way to get an issue fixed.

@threepointone
Copy link
Contributor

Closing this, happy to reopen if someone shares a reproducing case.

@cchamberlain
Copy link

cchamberlain commented Nov 9, 2019

I'm hitting this as well. It's hard to reproduce since it doesn't occur on every run. Only noticed after implementing a bunch of tests and merging my changes, which caused others builds to break (randomly). Makes jest feel pretty flaky.

This definitely seems to be related to async thunks. Definitely still a big current issue, so don't understand why it's closed.

Note: I checked one of my failing async thunk actions and it didn't have any console.log so not seeing that correlation on my end. This is a private repo so unfortunately can't share.

@threepointone
Copy link
Contributor

The most likely cause is that there’s some asynchronous work pending after your test completes, and it tried to update the dom after jest finishes running its tests and cleansup the jsdom instance. There’s not much that React can do here, since it has to be fixed in the test itself, by either cancelling that work, or waiting till it finishes before exiting the test.

That said, it’s hard to comment without a reproducing example. Keeping this issue open wouldn’t serve a purpose. If you can share a git repo with a reduced usecase that reproduces the error, even if only intermittently, I would be happy to help debug or give some pointers.

@ishristov
Copy link

...
There’s not much that React can do here, since it has to be fixed in the test itself, by either cancelling that work, or waiting till it finishes before exiting the test.
...

That's not entirely true as React could have accepted this PR and the issue would have been solved generally on their end.

@threepointone
Copy link
Contributor

The PR doesn’t solve the bug, it hides it.

@ivarprudnikov
Copy link

@threepointone I've come up with a reproducible example, although to be fair it would still need investigation to pin down exact/specific cause:

https://github.com/ivarprudnikov/test-react-enzyme-body-null

@unframework
Copy link

Hey folks, here is another reproduction of this issue with React and Jest (using React Testing Library this time): https://repl.it/repls/PeskyStimulatingBetaversion

It makes sense that whenever this happens the fix should be within the test itself, ultimately. However, the current error message is not very obvious.

There is already an example of such message here:

'The `document` global was defined when React was initialized, but is not ' +
. The getActiveElement check could also do something like that.

And of course in both of these situations checking for null in addition to undefined would also be helping to correctly show this descriptive message.

So, again, it is true that the root cause is ultimately outside of React code, but this could be a better developer experience when diagnosing it. Hope this helps and thanks for your tireless efforts!

@AvraamMavridis
Copy link

I have the same issue with react testing library, the only difference is that the test pass locally while fails on CI.

@jack-bliss
Copy link

@gaearon https://codesandbox.io/s/thirsty-snowflake-y5reo?file=/src/App.js

this is my attempt at a minimal recreation. the reason i would actually want to hit an endpoint is for doing automated integration testing, which i believe is a valid usecase.

@tarjei
Copy link

tarjei commented May 28, 2021

It would be very useful to get some information about which user-space function failed when this failure mode occurs. Is that possible? If not, maybe something like this could be added to react-dom.development.js:

 if (doc === null) {
          console.error("getActiveElement: document is null. This implies that an async process has finished after React has been mounted.")
          return null;
}

This will notify the user about the error - i.e. not hide it - but it will not crash the whole app.

@venik2007
Copy link

In my case switching between node versions (with nvm) helps me:
Now using node v12.18.0 (64-bit) vs Now using node v14.17.0 (32-bit)
image
image

@ggblee
Copy link

ggblee commented Apr 12, 2023

i ran into this problem with react router v5 and react v18 using react testing library v13
i was persisting my component throughout different states using

import '@testing-library/react/dont-cleanup-after-each'

turns out i needed to run cleanup() after all my tests and it works now!
e.g.

import { cleanup } from '@testing-library/react'

...
describe('whatever', () => {
    afterAll(() => { cleanup() })
})

i feel like the issue had something to do with test cleanup, as mentioned earlier in this thread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests