I am trying to make api calls using the useQuery
hook of @apollo/client but the loading props of the query is always true
so the Loader
is always shown. I first tried this by calling multiple useQuery
hooks one after another, but later found out that even a single query execution is giving this state. I am sharing the relevant details below. I read this answer but it spoke about versioning, which is not solving my problem. Here are my code, dependencies and details about where I am calling this hook.
Home.tsx
// necessary imports
import * as query from 'queries';
import {useQuery} from '@apollo/client';
let obj = {
"Skin":"",
"Hair":"",
"Beard":"",
"Wellness":"",
"Performance":""
}
const encode = (str:string):string => Buffer.from(str,'binary').toString('base64');
const Home = () => {
const queryString = query.GET_COLLECTIONS_BY_HANDLE;
const hair = useQuery(queryString.query,{
variables:{
handle:'hair'
}
});
const skin = useQuery(queryString.query,{
variables:{
handle:'skin'
}
});
const beard = useQuery(queryString.query,{
variables:{
handle:'beard'
}
});
const wellness = useQuery(queryString.query,{
variables:{
handle:'wellness'
}
});
const performance = useQuery(queryString.query,{
variables:{
handle:'performance'
}
});
if(hair.loading || skin.loading || wellness.loading || performance.loading || beard.loading){
console.log('Loading hair',hair.loading);
console.log('Loading skin',skin.loading);
console.log('Loading wellness',wellness.loading);
console.log('Loading beard',beard.loading);
console.log('Loading performance',performance.loading);
return <Loader/> // This is my custom Activity Indicator
}
if(hair.error || wellness.error || skin.error || performance.error || beard.error){
console.error(hair.error);
}
if(hair.data != undefined){
obj['Hair'] = hair.data.id;
}
if(skin.data != undefined){
obj['Skin'] = skin.data.id;
}
if(wellness.data != undefined){
obj['Wellness'] = wellness.data.id;
}
if(performance.data != undefined){
obj['Performance'] = performance.data.id;
}
if(beard.data != undefined){
obj['Beard'] = beard.data.id;
}
return (
//rendering the UI
)
}
export default Home
package.json
{
"dependencies": {
"@apollo/client": "^3.8.7",
//other packages
"react": "18.2.0",
"react-native": "0.72.6",
"react-native-collapsible": "^1.6.1",
"react-native-element-dropdown": "^2.10.1",
"react-native-gesture-handler": "^2.14.0",
"react-native-image-slider-show": "^1.0.3",
"react-native-keychain": "^8.1.2",
"react-native-reanimated": "^3.6.1",
"react-native-render-html": "^6.3.4",
"react-native-safe-area-context": "^4.7.4",
"react-native-screens": "^3.27.0",
"react-native-snackbar": "^2.6.2",
"react-native-vector-icons": "^10.0.2",
"ts-mixer": "^6.0.3"
},
"devDependencies": {
//development Dependencies
},
"engines": {
"node": ">=16"
}
}
Navigation structure : Drawer on Top -> Tab Navigation -> Stack Navigation.
When the App loads, the first screen shown in Home.tsx and the loader is continuously shown.
Using useQuery more than once in a component is an anti-pattern. You can run all those queries at once and only have one loading state. Simpler, faster, cleaner.
Example:
query twoQueries($p1: string!, $p2: string!) {
query1(p1: $p1) {
field1
field2
…
}
query2(p2: $p2) {
fieldA
fieldB
…
}
}