You need to follow two rules in order to use hooks,
- Call Hooks only at the top level of your react functions: You should always use hooks at the top level of react function before any early returns. i.e, You shouldn’t call Hooks inside loops, conditions, or nested functions. This will ensure that Hooks are called in the same order each time a component renders and it preserves the state of Hooks between multiple re-renders due to
useState and useEffect calls.
Let's see the difference using an example,
Correct usage::
function UserProfile() {
const [name, setName] = useState('John');
const [country, setCountry] = useState('US');
return (
<h1>Name: {name}</h1>
);
}
Incorrect usage::
function UserProfile() {
const [name, setName] = useState('John');
if (name === 'John') {
const [country, setCountry] = useState('US');
}
return (
<h1>Name: {name}</h1>
);
}
The useState hook for the country field is being called conditionally within an if block. This can lead to inconsistent state behavior and may cause hooks to be called in a different order on each re-render.
- Call Hooks from React Functions only: You shouldn’t call Hooks from regular JavaScript functions or class components. Instead, you should call them from either function components or custom hooks.
Let's find the difference of correct and incorrect usage with below examples,
Correct usage::
function Counter() {
const [count, setCount] = useState(0);
return <div>Counter: {count}</div>;
}
function useFetchData(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => setData(data));
}, [url]);
return data;
}
function UserProfile() {
const user = useFetchData('https://some-api.com/user');
return (
<h1>{user ? user.name : 'Loading profile...'}</h1>
);
}
Incorrect usage::
function normalFunction() {
const [count, setCount] = useState(0);
}
function fetchData(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => setData(data));
}, [url]);
return data;
}
In the above incorrect usage example, both useState and useEffect are used in non-React functions(normalFunction and fetchData), which is not allowed.