Invalid hook call when using react class component in MDX
Danielku15 opened this issue · comments
Initial checklist
- I read the support docs
- I read the contributing guide
- I agree to follow the code of conduct
- I searched issues and couldn’t find anything (or linked relevant results below)
Affected packages and versions
@mdx-js/react 3.0.1
Link to runnable example
No response
Steps to reproduce
I reproduced this problem faily easily with Docusaurus as explained here:
The answer of Josh shows how to reproduce the probelm using mdx-js loader. They sent me over to you as it seem the root cause sits in mdx-js.
Expected behavior
It should be possible declare React class components in MDX files without errors.
Actual behavior
When you try to declare react components using React.Component in MDX files you end up with an Invalid hook call. error.
- Setup an empty Docusuarus with latest dependencies
- npx create-docusaurus@latest my-website classic --typescript && npx ncu -u && npm i && npm start
- Open https://docusaurus.new/stackblitz-ts
- Open the
docs/tutorial-basics/markdown-features.mdx
- Change the file content to
---
sidebar_position: 4
---
import React from 'react'
export class Test extends React.Component {
render() {
return (<div>Title</div>);
}
}
<Test />
- Open the page in the browser.
- Experience the error.
Runtime
Node v20
Package manager
npm v10
OS
Windows
Build and bundle tools
Docusaurus
The exceptions from #2444 and the one I experience look a bit different. Seems I messed up things a bit on cross-posting. The error thrown in Docusaurus for me is:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
at Object.throwInvalidHookError (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:16227:9)
at Object.useContext (webpack-internal:///./node_modules/react/cjs/react.development.js:1619:21)
at useMDXComponents (webpack-internal:///./node_modules/@mdx-js/react/lib/index.js:47:64)
at Test.render (webpack-internal:///./docs/tutorial-basics/markdown-features.mdx:59:73)
at finishClassComponent (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:19747:31)
at updateClassComponent (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:19693:24)
at beginWork (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:21606:16)
at HTMLUnknownElement.callCallback (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:4164:14)
at Object.invokeGuardedCallbackDev (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:4213:16)
at invokeGuardedCallback (webpack-internal:///./node_modules/react-dom/cjs/react-dom.development.js:4277:31)
But the root cause could still be the same if there is some error handling in place which might change the message seen.
From what I understand is:
- Docusaurus renders pages via function components.
- https://github.com/facebook/docusaurus/blob/2152572a3b1ce970d267303a0031d1910776e979/packages/docusaurus-theme-classic/src/theme/DocItem/Content/index.tsx#L45
- https://github.com/facebook/docusaurus/blob/2152572a3b1ce970d267303a0031d1910776e979/packages/docusaurus-theme-classic/src/theme/MDXContent/index.tsx#L14
- This ends up in the react lib of this library:
mdx/packages/react/lib/index.js
Line 76 in 8f754f7
- Here the useContext hook is called:
mdx/packages/react/lib/index.js
Line 41 in 8f754f7
- As one of my components inbetween is a React.Component class we are in the render method of it.
- According to https://react.dev/warnings/invalid-hook-call-warning it is "bad" to call hooks within the render method inside class components.
It's not visible in my demo code but I am using class components because I currently use things like componentDidMount
. I might use alternatives like useEffect(()=>{}, [])
at some point but I'm not there yet. I'm wrapping a non-react component.
Funnily things work if I move the component into an own TSX file and import it to the MDX.
See also facebook/docusaurus#9905 (comment)
done :)