Reputation: 561
I am studying GraphQL/Apollow and React, now I want to fetch data using useQuery(or useLazyQuery). More specifically, I have two queries, query B is dependent on the result of query A, that is, I need to skip query B for some query A results, and not skip for other results. Moreover, I want to have loading spinner while fetching data.
My current solution: useEffect with [] parameters + useLazyQuery (Apollo) to only load data for one time, and at the same time updating loading state.
export const QUERY_A = gql `
// something
`
export const QUERY_B = gql `
// something
`
export default function ExampleModal(props: SomeType) {
const [apiStatus, setApiStatus] = React.useState({
loading: false,
error: false
});
let resultA = '';
const[getA] = useLazyQuery(QUERY_A, {
onCompleted: (data) => { // won't set loading to false, as we need to queryB
resultA = data?.getAquery.status
},
onError: (error) => {
setApiStatus({
loading: false,
error: true
});
},
});
let resultB = '';
const[getB] = useLazyQuery(QUERY_B, {
onCompleted: (data) => {
resultB = data?.getBquery.result;
setApiStatus({
loading: false,
error: false,
});
},
onError: (error) => {
setApiStatus({
loading: false,
error: true
});
},
},
skip: resultA == 'something' // this situation,we skip B
);
React.useEffect( () => {
setApiStatus({ // start loading
loading: true,
error: false
});
// fetch real data from A and B,
}, []); // use [] to just load for one time, when re-render, will not call apis again
if (apiStatus.loading) return <div> loading...<div>
if (apiStatatus.error) return <div> error...<div>
return <div> real result <div>
}
I know there may be a few issues here, my questions is:
setApiStatus({ // start loading
loading: true,
error: false
});
will the component re-render immediately??
const [apiStatus, setApiStatus] = React.useState({
loading: false,
error: false,
resultA: '',
resultB: '',
});
will this work?
thank you so much!
Upvotes: 2
Views: 695
Reputation: 585
setState
using Object.assign()
or separate loading
and error
.const [loading, setLoading] = React.useState(false)
const [error, setError] = React.useState(false)
You can use an empty useEffect and make API call to A conditionally if DATA A is undefined/null.
const [dataA, setDataA] = React.useState(null)
const [dataB, setDataB] = React.useState(null)
useEffect(() => {
!dataA && apiCallForA
}, [])
Upvotes: 1
Reputation: 1
you can | loadings like
const [callFirst, {loading:loadingFirst}] = useLazyQuery(
GET_QUERY,
{ variables: ... }
);
const [callFirst, {loading:loadingSecond}] = useLazyQuery(
GET_QUERY,
{ variables: ... }
);
return ((loadingFirst | loadingSecond) && loading...)
return <Component/>
or you can call multiple query in one query
export const MULTIPLE_QUERY=gql`
query ($id:Int){
post(id:$id){
id
title
}
comments(id:$id){
id
title
}
}
`
Upvotes: 0