CategoryContext
Description
Provides category page data to child components. Used only on category pages to access category information, products, filters, and price ranges.
Import
import { CategoryProvider, useCategory } from '@components/frontStore/catalog/CategoryContext';
Usage
Setup Provider
import { CategoryProvider } from '@components/frontStore/catalog/CategoryContext';
function CategoryPage({ category }) {
return (
<CategoryProvider category={category}>
{/* Category page components */}
</CategoryProvider>
);
}
Access Category Data
import { useCategory } from '@components/frontStore/catalog/CategoryContext';
function CategoryHeader() {
const category = useCategory();
return (
<div>
<h1>{category.name}</h1>
{category.description && <div>{category.description}</div>}
{category.image && <img src={category.image.url} alt={category.image.alt} />}
</div>
);
}
API
CategoryProvider Props
| Name | Type | Required | Description |
|---|---|---|---|
| category | CategoryData | Yes | Category data object |
| children | ReactNode | Yes | Child components |
useCategory Hook
Returns the complete CategoryData object. Throws error if used outside CategoryProvider.
CategoryData Interface
| Field | Type | Description |
|---|---|---|
| categoryId | number | Category ID |
| uuid | string | Category UUID |
| name | string | Category name |
| description | Array<Row> | Rich text description |
| url | string | Category URL |
| image | object | Category image (url, alt) |
| showProducts | boolean | Whether to display products |
| products | CategoryProducts | Product listing data |
| availableAttributes | FilterableAttribute[] | Filterable attributes |
| children | CategoryFilter[] | Child categories |
| priceRange | object | Price range (min, max) |
CategoryProducts Interface
interface CategoryProducts {
items: ProductData[]; // Array of products
currentFilters: FilterInput[]; // Active filters
total: number; // Total product count
}
Price Range Object
interface PriceRange {
min: number; // Minimum price value
minText: string; // Formatted min price
max: number; // Maximum price value
maxText: string; // Formatted max price
}
Examples
Display Category Info
import { useCategory } from '@components/frontStore/catalog/CategoryContext';
function CategoryInfo() {
const { name, description, image, products } = useCategory();
return (
<div className="category-info">
{image && (
<img src={image.url} alt={image.alt} className="category-banner" />
)}
<h1>{name}</h1>
{description && <div className="description">{description}</div>}
<p>{products.total} products</p>
</div>
);
}
Product Listing
import { useCategory } from '@components/frontStore/catalog/CategoryContext';
function ProductList() {
const { products, showProducts } = useCategory();
if (!showProducts) {
return null;
}
return (
<div className="product-grid">
{products.items.map(product => (
<div key={product.productId}>
<h3>{product.name}</h3>
<p>{product.price.text}</p>
</div>
))}
</div>
);
}
Price Filter
import { useCategory } from '@components/frontStore/catalog/CategoryContext';
function PriceFilter() {
const { priceRange } = useCategory();
return (
<div className="price-filter">
<h3>Price Range</h3>
<p>From {priceRange.minText} to {priceRange.maxText}</p>
<input
type="range"
min={priceRange.min}
max={priceRange.max}
/>
</div>
);
}
Subcategories
import { useCategory } from '@components/frontStore/catalog/CategoryContext';
function Subcategories() {
const { children } = useCategory();
if (!children || children.length === 0) {
return null;
}
return (
<div className="subcategories">
<h3>Shop by Category</h3>
<ul>
{children.map(child => (
<li key={child.categoryId}>
<a href={child.url}>{child.name}</a>
</li>
))}
</ul>
</div>
);
}
Active Filters Display
import { useCategory } from '@components/frontStore/catalog/CategoryContext';
function ActiveFilters() {
const { products } = useCategory();
if (products.currentFilters.length === 0) {
return null;
}
return (
<div className="active-filters">
<h4>Active Filters:</h4>
{products.currentFilters.map((filter, index) => (
<span key={index} className="filter-tag">
{filter.key}: {filter.value}
</span>
))}
</div>
);
}
Complete Category Page
import { CategoryProvider, useCategory } from '@components/frontStore/catalog/CategoryContext';
import { Image } from '@components/common/Image';
function CategoryPageContent() {
const category = useCategory();
const { name, description, image, products, priceRange, children } = category;
return (
<div className="category-page">
{/* Category Header */}
<div className="category-header">
{image && <Image src={image.url} alt={image.alt} width={1200} height={400} />}
<h1>{name}</h1>
{description && <div className="description">{description}</div>}
</div>
{/* Subcategories */}
{children.length > 0 && (
<div className="subcategories">
<h3>Categories</h3>
<div className="category-grid">
{children.map(child => (
<a key={child.categoryId} href={child.url}>
{child.name}
</a>
))}
</div>
</div>
)}
{/* Products Section */}
{category.showProducts && (
<>
<div className="results-bar">
<p>{products.total} products found</p>
{products.currentFilters.length > 0 && (
<div className="active-filters">
{products.currentFilters.map((filter, i) => (
<span key={i}>{filter.key}: {filter.value}</span>
))}
</div>
)}
</div>
<div className="product-listing">
{products.items.map(product => (
<div key={product.productId} className="product-card">
<h3>{product.name}</h3>
<p>{product.price.text}</p>
</div>
))}
</div>
</>
)}
</div>
);
}
export default function CategoryPage({ categoryData }) {
return (
<CategoryProvider category={categoryData}>
<CategoryPageContent />
</CategoryProvider>
);
}
Features
- Category Metadata: Name, description, image, URL
- Product Listing: Filtered products with pagination
- Filter Support: Current filters and available attributes
- Price Range: Min/max prices for filtering
- Subcategories: Child category navigation
- Extended Fields: Support for custom fields
- Type Safe: Full TypeScript support
- Error Handling: Throws error if used outside provider
Usage Notes
- Only available on category pages
- Must wrap components in
CategoryProvider - The
useCategoryhook throws error if used outside provider - Description is rich text (array of Row objects)
- Extended fields allow custom category data
Related Components
- ProductFilter - Product filtering
- ProductContext - Single product context
- Image - Image component