#CSS grid loading state

5 messages · Page 1 of 1 (latest)

late flame
#

I have a CSS grid that loads a server preloaded first page and also uses usePaginatedQuery. I want to make a loading state, but only when the results of usePaginatedQuery are displayed. If the preloaded results are displayed, there should be no loading state. Also I want the transition of the properties updating on the grid to be clean. Currently the properties just vanish and it's not ideal. This grid is displayed properties (buildings) in Virginia.

fathom pivotBOT
#

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

#

To achieve a smooth loading state for your CSS grid that only appears when usePaginatedQuery is fetching data (and not when displaying server-preloaded results), you need to carefully manage when you show the loading indicator and how you transition between states.

Key Points from Convex Documentation

  • usePaginatedQuery returns an object with results, isLoading, and status. The isLoading flag is true when the hook is loading results, and false otherwise. The results array contains the currently loaded items, which will be empty until the first page is loaded unless you hydrate it with preloaded data yourself [Paginating within React Components].
  • If you want to avoid a flash or abrupt disappearance of grid items when loading new data, you can use a "stable" query pattern. This involves keeping the previous results visible until the new data is ready, as shown in the useStablePaginatedQuery example [What about pagination, is that a complication?].

Implementation Strategy

  1. Hydrate the grid with preloaded data: Render your preloaded properties as the initial state of the grid.
  2. Use usePaginatedQuery for subsequent data: When the hook loads, only show the loading state if the grid is displaying data from usePaginatedQuery and not from the preloaded data.
  3. Keep previous results during loading: Use a stable paginated query pattern to avoid abrupt transitions or empty states while new data is loading.
  4. CSS Transitions: Use CSS transitions or animations to smoothly update the grid when new properties are loaded.

Example Approach

#
import { useRef } from "react";
import { usePaginatedQuery } from "convex/react";
import { api } from "../convex/_generated/api";

// Custom hook to keep previous results during loading
function useStablePaginatedQuery(query, args, options, preloadedResults) {
  const result = usePaginatedQuery(query, args, options);
  const stored = useRef({ ...result, results: preloadedResults });

  // Only update stored results when not loading more
  if (result.status !== "LoadingMore" && result.status !== "LoadingFirstPage") {
    stored.current = result;
  }
  return stored.current;
}

export function PropertiesGrid({ preloadedProperties }) {
  const { results, status, isLoading, loadMore } = useStablePaginatedQuery(
    api.properties.listInVirginia,
    {},
    { initialNumItems: 20 },
    preloadedProperties
  );

  // Show loading indicator only if not showing preloaded data
  const showLoading = isLoading && results !== preloadedProperties;

  return (
    <div className={`grid properties-grid ${showLoading ? "loading" : ""}`}>
      {results.map((property) => (
        <PropertyCard key={property._id} {...property} />
      ))}
      {showLoading && <div className="loading-indicator">Loading...</div>}
      {status === "CanLoadMore" && (
        <button onClick={() => loadMore(20)}>Load More</button>
      )}
    </div>
  );
}

CSS Example for Smooth Transitions

.properties-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1rem;
  transition: opacity 0.3s;
}
.properties-grid.loading {
  opacity: 0.5;
}
.loading-indicator {
  grid-column: 1 / -1;
  text-align: center;
  animation: fadeIn 0.3s;
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

Summary

#
  • Hydrate your grid with preloaded data.
  • Use a stable paginated query pattern to avoid flashes or abrupt transitions.
  • Only show the loading state when usePaginatedQuery is fetching and not when preloaded data is displayed.
  • Use CSS transitions for a smooth UI update.

This approach is based on the recommended patterns for stable queries and paginated queries in Convex [What about pagination, is that a complication?]. If you need more advanced cache control or want to persist loaded pages across navigation, you may need to manage the paginated results in a global state, as discussed in community threads.

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