I’m trying to make reusable GET
and POST
requests, but I’m getting error Invalid hook call
when setting the data
state in the reusable fetch request component. I’ve just learnt that we can only use hooks in React components, so how can I make that functionality reusable?
import axios from "axios";
import { useContext, useEffect, useState } from "react";
import AuthContext from "../../context/Auth-context/AuthContext";
import { useNavigate } from "react-router-dom";
export const POST = (url, body, credentials) => {
const [data, setData] = useState([]);
const [isLoaded, setIsLoaded] = useState(false);
const [error, setError] = useState(null);
const { dispatch } = useContext(AuthContext);
const navigate = useNavigate();
useEffect(() => {
const fetchData = () => {
axios
.post(url, body, { withCredentials: credentials })
.then((response) => {
setIsLoaded(true);
setData(response.data);
})
.catch((error) => {
if (error.status === 401) {
dispatch({ type: "LOGOUT" });
navigate("/login");
return;
}
setError(error);
});
};
fetchData();
}, [url, credentials, dispatch, navigate, body]);
return { error, isLoaded, data };
};
const approve = async (id) => {
const { data, error, isLoaded } = POST(
"http://localhost:8000/api/new-users",
id,
true
);
if (error) {
return (
<Error/>
);
}
if (!isLoaded) {
return (
<Loader/>
);
}
console.log(data);
};
2
Answers
Rename the
POST
into ‘usePost’ and check.https://react.dev/learn/reusing-logic-with-custom-hooks#hook-names-always-start-with-use
The code is breaking React’s Rules of Hooks. React hooks, i.e.
useState
,useNavigate
, etc, can only be called in React functions and custom React hooks, andPOST
is neither of these. The trivial solution would be to simply renamePOST
to be a valid React hook, e.g. using the"use-"
prefix on the identifier. The issue then is that you would be callingusePost
in a callback which again breaks React’s Rules of Hooks.I suggest a refactor to return a "trigger" function that handles the fetch (instead of
useEffect
) which can be called in a callback.Example:
Usage: