I’m working on some code that’s using React. It’s added to the page like this:
ReactDom.render(MyClass.render(), document.getElementById('app-id'));
MyClass
is defined as a generic class:
import App from "./App";
class MyClass {
constructor(props) {
this.props = props;
}
render() {
return App(this.props);
}
}
window.MyClass = MyClass;
and App
is defined (generally) as
const App = (props) => {
return (
<Provider store={store} />
);
};
export default App;
I want to useState
within App
as I need to pass that state variable and function throughout some code, but the moment that I change the App component to
import { useState } from 'react';
const App = (props) => {
const [ selectedStore, setSelectedStore ] = useState(store);
return (
<Provider store={store} />
);
};
then I get an error in the console:
Uncaught 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
What am I missing to allow the ability to useState
within App
?
2
Answers
Rules of hooks require that they are called at the top level of a function component or a custom hook. In your case, the
App
component is defined as a function component, but it’s being used as a regular component byMyClass.render()
.You must change the definition of App to be a functional component.
And then you use
App
inMyClass
component as before.You are using a react hook, useState can only be called in functional components.
It is stated in the react official docs that you have to
So what is functional component in React?
React components are regular JavaScript functions except:
What is the problem?
in your case, you are calling the app as function
When a function is called directly as
Component()
it will just run and return something. No lifecycle, no hooks, none of the React magic. It’s very similar to assigning some JSX to a variable, but with more flexibility (you can use if statements, switch, throw, etc.).When a functional component is used as
<Component />
it will have a lifecycle and can have a state.If you have to declare a function that returns JSX inside a functional component or class component and would use one of the react hooks i.e.
React.useState
Solution
you might call it as in the following
OR
References: