I am writing a reactjs web app where I need to initially load a list of resorts, and then, after the user selects one of them, load all the details of thet resort.
This is my useFetch function:
const useFetch = (url, options) => {
const [response, setResponse] = React.useState(null);
const [error, setError] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(false);
React.useEffect(() => {
(async () => {
setIsLoading(true);
try {
const res = await fetch(url, options);
const json = await res.json();
setResponse(json);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
})();
}, []);
return [ response, error, isLoading ];
};
In my component, I use it to retrieve the resorts list, without any problem:
function App() {
const [resorts, resortsIsLoading, resortsError] = useFetch(config.API_URL_GET_RESORTS);
const [resortId, setResortId] = useState(null);
const handleChangeResort = (event) => {
const id = event.target.value;
setResortId(id);
};
return (
<>
<Select
labelId="resort-label"
id="resort"
label="resort"
value={resort ? resort.id : ""}
onChange={handleChangeResort}
>
{resorts.length ? (
resorts.map(c => (
<MenuItem key={c.id} value={c.id}>
{c.name}
</MenuItem>
))
) : (
<MenuItem key={0} value={""}>
<em>loading resorts list...</em>
</MenuItem>
)}
</Select>
</>
)}
}
The problem is that I cannot add a useFetch to get the selected resort details after the first useFetch call:
const [resorts, resortsIsLoading, resortsError] = useFetch(config.API_URL_GET_RESORTS);
const [resort, resortIsLoading, resortError] = useFetch(config.API_URL_GET_RESORT, {id: resortId});
because I don't yet have the resortId, initially.
I would need something like:
useEffect(() => {
if (resortId !== null) {
const [resort, resortIsLoading, resortError] = useFetch(config.API_URL_GET_RESORT, {id: resortId});
}
}, [resortId]);
but hooks cannot be used inside useEffect()...
What solution should I adopt to use the useFetch() logic (which I like very much, because it hides the details of the fetch from the mail app logic) in a conditional way (i.e.: after the resortId is available) ?
return [ response, isLoading, error ];as you are using array everywhere when calling useFetch