Skip to content

Best Practices

1. Use Appropriate Fragments

ts
// ✅ Good: Use minimal fragment for listings
const { data } = await graphqlRequest(GET_PRODUCTS, {
  // Uses PRODUCT_CORE_FRAGMENT
});

// ❌ Bad: Fetching unnecessary data
const { data } = await graphqlRequest(GET_PRODUCT_BY_ID, {
  // Uses PRODUCT_DETAILED_FRAGMENT (too much for listings)
});

2. Parallel Data Fetching

ts
// ✅ Good: Fetch in parallel
const [products, filters] = await Promise.all([
  graphqlRequest(GET_PRODUCTS, {}),
  graphqlRequest(GET_FILTER_OPTIONS, {}),
]);

// ❌ Bad: Sequential fetching
const products = await graphqlRequest(GET_PRODUCTS, {});
const filters = await graphqlRequest(GET_FILTER_OPTIONS, {});

3. Implement Proper Caching

typescript
// ✅ Good: Cache with appropriate lifetime
const data = await graphqlRequest(
  GET_PRODUCTS,
  { query: "laptop" },
  {
    tags: ["products"],
    life: "hours", // Cache for 1 hour
  }
);

// ❌ Bad: No caching
const data = await graphqlRequest(
  GET_PRODUCTS,
  { query: "laptop" },
  { noCache: true }
);

4. Handle Empty States

ts
// ✅ Good: Proper empty state handling
const products = data?.products?.edges?.map((e) => e.node) || [];

if (products.length === 0) {
  return <NoProductsFound searchQuery={searchValue} />;
}

return <ProductGrid products={products} />;

5. Optimize Pagination

ts

// ✅ Good: Use lightweight query for cursor calculation
const cursorData = await graphqlRequest(GET_PRODUCTS_PAGINATION, {
  first: currentPage * itemsPerPage,
});

// ❌ Bad: Fetching full product data just for cursor
const cursorData = await graphqlRequest(GET_PRODUCTS, {
  first: currentPage * itemsPerPage,
});

6. URL State Management

ts

// ✅ Good: Use URL params for all state
const searchParams = {
  q: searchValue,
  page: currentPage,
  sort: sortValue,
  color: selectedColors.join(","),
};

// ❌ Bad: Using local state (not shareable/bookmarkable)
const [filters, setFilters] = useState({});

Released under the MIT License.