To get certain data, I need to call multiple custom hooks, all of which are making api requests to get some data, then after each call, I need to use gotten data to pass to the next custom hook to get the next data.
- If I put the all the calls except the first one into a useEffect hook and the needed data into the dependency array this will give me an error as I cant call custom hooks conditionally inside an effect.
- Or should I call the first one inside a useEffect, then storing result in state and then just have a simple if statement, so if there is state, call the other hooks
const useSomeCustomData = ({ids}) => {
const { data: firstData } = useFirstData({
ids: ids,
});
const investmentIds = firstData?.investments.map(
(investment) => investment?.id
);
//next one depending on previously gotten investmentIds
const { data: secondData } = useSecondData({
investmentId: investmentIds ? investmentIds : undefined,
});
const start = secondData?.products?.map((product) => {
return product.date;
})[0];
//next one depending on previously gotten "start" from secondData
const { data: thirdData } =
useThirdData({
startDate: start,
});
}
2
Answers
As built-in hooks, custom hooks are also part of a component’s body. It takes part in rendering a component. Therefore it is illegal to invoke a built-in or a custom hook in the handler of the useEffect hook. As we know, the handler of this hook runs only after rendering the component.
One of the most elementary custom hooks which wraps a network fetch may be written in the pattern as “feed the url and get the data out”. The following custom hook works on that basis.
When the above custom hook is used to retrieve a set of related data, we can chain the hooks as the below code does. It means the output of one hook is fed to another and so on. The custom hook useSomeCustomData below chains the three elementary data hooks and get the final data. The most important aspect in the below code is the “reactive value” url used in the “dependency array” of the three hooks, whenever the url will change with respect to the query strings, then the chain of hooks will automatically restart to execute.
App.js
Test run
On initial load
After the mocked async calls
On clicking Fetch again button
After the mocked async calls
This is not a hooks problem, its a design pattern issue.
If you have a bunch of changed queries which need to fetch some data, wrap those in an async function and use that
queryFn
in a useEffect.Chaining of queries is just a
.then
chain on first fetch.You can have multiple states wired up to your
queryFn
and have setState calls in each step.Instead of using your hook multiple times, move the query chain inside that hook, and use it once.