How do I write a React component as a function correctly for React Hooks?
When I attempt to write my component as a function:
"use strict"
function App() {
const [foo, setFoo] = React.useState()
const element = React.createElement()
return element
}
function appRender() {
const appContainerElement = document.getElementById('app-container')
const appComponent = App()
ReactDOM.render(appComponent, appContainerElement)
}
The React library emits an error:
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.
That component is pretty simple, it's hard to see how it fails to be a function component. The index document directly loads the React and React DOM libraries with the same version. I believe the component is “following the Rules of Hooks”.
Note that this is using React without JSX, as the ReactJS documentation describes. The React component creates an element and returns it.
The index document loads the React libraries and invokes the ‘appRender’ function after all modules are loaded:
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8" />
<script src="https://unpkg.com/react@17/umd/react.development.js"
crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"
crossorigin></script>
<script src="/js/app.js"></script>
<script defer>
window.addEventListener('load', ((event) => {
appRender()
}))
</script>
</head>
<body>
<div id="app-container">
<div id="app" class="initial-placeholder">
<p class="loading-status">Preparing the app…</p>
</div><!-- #app -->
</div><!-- #app-container -->
</body>
</html>
This correctly invokes the ‘appRender’ function.
What is the error? How do I correct this component so I can use React Hooks in it?
App? You also don't invoke your component (e.g.<App />instead ofApp()), you pass the JSX to the React framework and it handles invoking and computing the renderable content. JSX is syntactic sugar aroundcreateElement. reactjs.org/docs/react-without-jsx.html