we use useQuery hook in the following way
function Dogs({ onDogSelected }) {
const { loading, error, data } = useQuery(GET_DOGS);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
return (
<select name='dog' onChange={onDogSelected}>
{data.dogs.map((dog) => (
<option key={dog.id} value={dog.breed}>
{dog.breed}
</option>
))}
</select>
);
}
here we are using destructuring assignment syntax and defining a const variable loading and assigning it to the loading property of the useQuery result object. But as loading is of boolean type, hence this variable is assigned according to pass by value, then how this variable changes to false as initially it is true. As the variable is const, so this value should not change. I am not able to understand what happens behind the scenes when useQuery is used?
2
Answers
It doesn’t. The
loading
const you get during the first call to your component function never changes. But later, when the ajax call finishes,useQuery
updates a state member, which makes React call your component function again to re-render. In that call,useQuery
returns a new value for the newloading
const that’s specific to that function call. This is just likeuseState
, which always returns the up-to-date state value.That happens because
useQuery
is using and updating state members in its code, ones you only see indirectly via its return value. Since you’re calling it during the render call to your component function, those state members are stored in your component instance’s state data, so updating them makes your component re-render.Let’s mock it up with our own stand-in for
useQuery
that just waits a moment then returns a random number, so we can see the code doing what the code "hidden" away inuseQuery
is doing (it’s not really hidden, it’s open source, but…):The
useDelayedRandom
hook waits a second, then generates a random number and does a state update (setRand(rand)
). That state is held in your component instance (behind the scenes in React’s internals), so updating it schedules the re-render.useQuery
is doing much the same, but updating in response to the ajax call completing rather than a timer.The React Query docs at tanstack.com/query/latest/docs/framework/react/overview should answer this. Your
<Dogs>
component is (or should be) wrapped in a<QueryClientProvider>
. I believe this outer<QueryClientProvider>
is responsible for rerendering your<Dogs>
component untiluseQuery()
returns data.