I want to create a custom hook that allows me to fetch some data whenever I like it to do so. The hook should return a function that I can call anywhere within my code to fetch the data, and also a variable that then holds the response. Also, it should return the status of the fetch to me.
My hook looks like this:
import React, { useState } from "react";
import { AppListResponse } from "../../typings/AppListResponse";
const useFetchAppList = (
userId: string,
authToken: string
): [() => Promise<void>, (value: React.SetStateAction<string>) => void, string, AppListResponse | null | undefined] => {
const [status, setStatus] = useState<string>("idle");
const [responseData, setData] = useState<AppListResponse | null>();
const url = `https://my-endpoint.com/lets-fetch-this`;
const options = {
method: "GET",
headers: {
CustomAuthToken: authToken,
UserID: userId,
Accept: "application/json",
"Content-Type": "application/json"
}
};
const fetchAppList = async (): Promise<void> => {
setStatus("fetching");
try {
const response = await fetch(url, options);
const json = await response.json();
setData(json);
setStatus("successful");
} catch (error) {
console.log("error", error);
}
};
return [fetchAppList, setStatus, status, responseData];
};
export default useFetchAppList;
I try to call it like so:
const [fetchAppList, setStatus, status, data] = useFetchAppList(userId, authToken);
useEffect(() => {
const fetchData = async (): Promise<void> => {
await fetchAppList();
};
fetchData();
console.log(data, status);
}, []);
The problem is that the console.log(data)
returns undefined
, and the status
has the default value it starts with, which is idle
.
How can I make this work, so that I can call fetchAppList()
whenever I need, which will in turn return the data I need?
CodePudding user response:
In the component file (second code, where you are calling useFetchAppList
), You need to capture the data
and status
outside the useEffect
you specified. The useEffect
in your code runs only once on initial render and it remembers(closures) the value of data
and status
at the time it is invoked. Which is initially set as undefined
and "idle"
by the hook useFetchAppList
.
To see what is actually happening add below code as well to your second file
useEffect(() => {
console.log(data, status);
});
You will see different console items. First it would be "idle"
then it should be "fetching"
and finally it would be "successful" or "error"