#Is there a way to check if useQuery is loading?

5 messages · Page 1 of 1 (latest)

dusty path
#

The components that depend on a query often flicker as empty before showing the results. How can I determine if useQuery is currently loading?

hard zenithBOT
#

Hi @dusty path. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Yes, you can check if a Convex useQuery is loading by checking if the returned value is undefined. When useQuery is first mounted or when the query parameters change, it returns undefined until the data is loaded from Convex.

Handling Loading States

The flickering you're experiencing is a common issue with reactive queries. When the query parameters change, useQuery returns undefined while fetching new data, which can cause UI elements to briefly disappear before showing the new results.

const data = useQuery(api.functions.myQuery, { param });
return data === undefined ? "Loading..." : <DisplayData data={data} />;

Solutions to Prevent Flickering

1. Use a Custom Stable Query Hook

You can create a custom hook that maintains the previous query result while loading new data:

import { useRef } from 'react';
import { useQuery } from 'convex/react';

export const useStableQuery = ((query, ...args) => {
  const result = useQuery(query, ...args);
  const stored = useRef(result);
  
  if (result !== undefined) {
    stored.current = result;
  }
  
  return stored.current;
}) as typeof useQuery;

This hook will return the previous data while new data is loading, preventing the flickering effect Stack > Help, my app is overreacting!.

2. Enhanced Stable Query with Loading Status

If you need to know the loading state while still showing stable data, you can modify the hook:

import React from 'react';
import { OptionalRestArgsOrSkip, useQuery } from 'convex/react';
import { FunctionReference } from 'convex/server';
#

export function useStableQuery<Query extends FunctionReference<'query'>>(
query: Query,
...args: OptionalRestArgsOrSkip<Query>
): {data: Query['_returnType'] | undefined; isLoading: boolean} {
const result = useQuery(query, ...args);
const stored = React.useRef(result);
if (result !== undefined) {
stored.current = result;
}
return {data: stored.current, isLoading: result === undefined};
}


This gives you both stable data and loading status [Discord support thread: stable query with status](<https://discord.com/channels/1019350475847499849/1350461175296692327>).

### 3. For Paginated Queries

If you're using pagination, you can create a similar stable hook for paginated queries:

```javascript
import { useRef } from 'react';
import { usePaginatedQuery } from 'convex/react';

export const useStablePaginatedQuery = ((name, ...args) => {
  const result = usePaginatedQuery(name, ...args);
  const stored = useRef(result);

  if (result.status !== 'LoadingMore') {
    stored.current = result;
  }

  return stored.current;
}) as typeof usePaginatedQuery;

This prevents flickering when paginated query parameters change Stack > Help, my app is overreacting!.

4. Using TanStack Query

If you're using TanStack Query with Convex, it provides built-in loading states:

import { useQuery } from "@tanstack/react-query";
import { convexQuery } from "@convex-dev/react-query";
import { api } from "../convex/_generated/api";

export function App() {
  const { data, isPending, error } = useQuery(
    convexQuery(api.functions.myQuery, { id: 123 }),
  );
  return isPending ? "Loading..." : data;
}
#

This gives you explicit loading states through the isPending property Client > Convex with TanStack Query.

By implementing one of these approaches, you can maintain a smooth user experience without the flickering effect when query parameters change.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: