Skip to content

Store Configuration ​

Performance optimization and custom comparison strategies for complex store scenarios.

Prerequisites ​

For basic store setup and configuration patterns, see Basic Store Setup.

This document demonstrates advanced configuration using the Setup patterns:

Overview ​

Advanced configuration provides fine-grained control over store behavior, comparison strategies, and performance optimization for complex applications, built on established Setup patterns.

Performance-Optimized Configuration ​

tsx
import { createStoreContext } from '@context-action/react';

// Using ProductStores pattern from Setup with performance optimization
interface OptimizedProductStores {
  catalog: Product[];
  categories: Category[];
  filters: {
    category?: string;
    priceRange?: { min: number; max: number };
    searchTerm?: string;
    sortBy?: 'name' | 'price' | 'rating';
  };
  cart: {
    items: CartItem[];
    total: number;
    discounts: Discount[];
  };
}

const {
  Provider: ProductStoreProvider,
  useStore: useProductStore,
  useStoreManager: useProductStoreManager
} = createStoreContext<OptimizedProductStores>('Product', {
  // Large catalog - reference equality for performance
  catalog: {
    initialValue: [] as Product[],
    strategy: 'reference' as const,  // Reference equality for performance
    debug: true,                     // Enable debug logging
    description: 'Product catalog with reference equality'
  },
  
  // Categories with shallow comparison
  categories: {
    initialValue: [] as Category[],
    strategy: 'shallow' as const,
    description: 'Product categories with shallow comparison'
  },
  
  // Complex filters with deep comparison
  filters: {
    initialValue: {
      category: undefined,
      priceRange: undefined,
      searchTerm: undefined,
      sortBy: undefined
    },
    strategy: 'deep' as const,       // Deep comparison for nested changes
    comparisonOptions: {
      ignoreKeys: ['timestamp'],     // Ignore specific keys
      maxDepth: 5                    // Limit comparison depth
    }
  },
  
  // Shopping cart with custom comparison
  cart: {
    initialValue: { items: [], total: 0, discounts: [] },
    strategy: 'shallow' as const,
    comparisonOptions: {
      customComparator: (oldCart, newCart) => {
        // Custom comparison logic for cart optimization
        return oldCart.items.length === newCart.items.length &&
               oldCart.total === newCart.total;
      }
    }
  }
});

Comparison Strategies ​

Reference Strategy ​

tsx
// Best for: Large arrays, objects where reference changes indicate updates
// Using the ProductStores pattern from Setup guide with reference strategy
const {
  Provider: ProductStoreProvider,
  useStore: useProductStore
} = createStoreContext<ProductStores>('Product', {
  catalog: {
    initialValue: [] as Product[],
    strategy: 'reference' as const // Only re-render if array reference changes
  },
  
  categories: {
    initialValue: [] as Category[],
    strategy: 'reference' as const // Perfect for immutable data structures
  },
  
  filters: {
    initialValue: {},
    strategy: 'reference' as const
  },
  
  cart: {
    initialValue: { items: [], total: 0, discounts: [] },
    strategy: 'reference' as const
  }
});

Shallow Strategy ​

tsx
// Best for: Objects where top-level properties change
// Using UIStores pattern from Setup guide
const {
  Provider: UIStoreProvider,
  useStore: useUIStore
} = createStoreContext<UIStores>('UI', {
  modal: {
    initialValue: { isOpen: false, type: undefined, data: undefined },
    strategy: 'shallow' as const // Re-render if any top-level property changes
  },
  
  loading: {
    initialValue: { global: false, operations: {} },
    strategy: 'shallow' as const // Good for loading state
  },
  
  notifications: {
    initialValue: { items: [], maxVisible: 5 },
    strategy: 'shallow' as const // Good for notification state
  },
  
  navigation: {
    initialValue: { currentRoute: '', history: [], params: {} },
    strategy: 'shallow' as const
  }
});

Deep Strategy ​

tsx
// Best for: Nested objects where deep changes need detection
// Using UserStores pattern from Setup guide with deep configuration
const {
  Provider: UserStoreProvider,
  useStore: useUserStore
} = createStoreContext<UserStores>('User', {
  profile: {
    initialValue: { id: '', name: '', email: '', role: 'guest' },
    strategy: 'deep' as const, // Detects changes at any nesting level
    comparisonOptions: {
      maxDepth: 10,  // Prevent infinite recursion
      ignoreKeys: ['timestamp', 'lastUpdated'] // Ignore timestamp fields
    }
  },
  
  preferences: {
    initialValue: { theme: 'light', language: 'en', notifications: true },
    strategy: 'deep' as const,
    comparisonOptions: {
      maxDepth: 5
    }
  },
  
  session: {
    initialValue: { isAuthenticated: false, permissions: [], lastActivity: 0 },
    strategy: 'deep' as const,
    comparisonOptions: {
      ignoreKeys: ['lastActivity'] // Ignore frequent updates
    }
  }
});

Custom Comparison Options ​

Ignore Keys Pattern ​

tsx
// Using FormStores pattern from Setup guide with ignore keys
interface TrackingFormStores {
  userActivity: {
    userId: string;
    actions: string[];
    timestamp: number;
    sessionId: string;
  };
}

const {
  Provider: FormStoreProvider,
  useStore: useFormStore
} = createStoreContext<TrackingFormStores>('Form', {
  userActivity: {
    initialValue: { 
      userId: '', 
      actions: [], 
      timestamp: 0, 
      sessionId: '' 
    },
    strategy: 'shallow' as const,
    comparisonOptions: {
      ignoreKeys: ['timestamp', 'sessionId'] // Don't re-render for these changes
    }
  }
});

Custom Comparator Pattern ​

tsx
// Extending ProductStores pattern with custom comparison for search results
interface AdvancedProductStores extends ProductStores {
  searchResults: SearchResult[];
  coordinates: { x: number; y: number };
}

const {
  Provider: ProductStoreProvider,
  useStore: useProductStore
} = createStoreContext<AdvancedProductStores>('Product', {
  // Base ProductStores fields
  catalog: [] as Product[],
  categories: [] as Category[],
  filters: {},
  cart: { items: [], total: 0, discounts: [] },
  
  // Advanced fields with custom comparison
  searchResults: {
    initialValue: [] as SearchResult[],
    comparisonOptions: {
      customComparator: (oldResults, newResults) => {
        // Custom logic: only re-render if result count or first item changes
        return oldResults.length === newResults.length && 
               oldResults[0]?.id === newResults[0]?.id;
      }
    }
  },
  
  coordinates: {
    initialValue: { x: 0, y: 0 },
    comparisonOptions: {
      customComparator: (oldCoords, newCoords) => {
        // Only re-render if movement is significant (>5px)
        const distance = Math.sqrt(
          Math.pow(newCoords.x - oldCoords.x, 2) + 
          Math.pow(newCoords.y - oldCoords.y, 2)
        );
        return distance < 5;
      }
    }
  }
});

Debug Configuration ​

tsx
// Using UIStores pattern from Setup guide with debug configuration
const {
  Provider: UIStoreProvider,
  useStore: useUIStore
} = createStoreContext<UIStores>('UI', {
  modal: {
    initialValue: { isOpen: false, type: undefined, data: undefined },
    debug: true,  // Enable detailed logging
    tags: ['ui', 'modal'], // Tags for filtering logs
    version: '2.1.0', // Version for debugging
    description: 'Modal state with debugging enabled'
  },
  
  loading: {
    initialValue: { global: false, operations: {} },
    debug: true,
    description: 'Loading state tracking'
  },
  
  notifications: {
    initialValue: { items: [], maxVisible: 5 },
    debug: true,
    tags: ['notifications', 'critical'],
    description: 'Critical notification system'
  },
  
  navigation: {
    initialValue: { currentRoute: '', history: [], params: {} },
    debug: false // Disable debug for frequently changing navigation
  }
});

// Debug output example:
// [Store:UI:modal] Value changed: { isOpen: true, type: 'confirmation' }
// [Store:UI:notifications] Subscribers notified: 3
// [Store:UI:loading] Performance: 0.23ms

Performance Monitoring ​

tsx
// Using ProductStores pattern with performance tracking
interface MonitoredProductStores extends ProductStores {
  performanceData: {
    metrics: PerformanceMetric[];
    alerts: Alert[];
  };
}

const {
  Provider: ProductStoreProvider,
  useStore: useProductStore
} = createStoreContext<MonitoredProductStores>('Product', {
  // Standard ProductStores fields
  catalog: [] as Product[],
  categories: [] as Category[],
  filters: {},
  cart: { items: [], total: 0, discounts: [] },
  
  // Performance monitoring store
  performanceData: {
    initialValue: { metrics: [], alerts: [] },
    strategy: 'shallow' as const,
    debug: true,
    description: 'Performance monitoring data',
    comparisonOptions: {
      customComparator: (oldData, newData) => {
        // Log performance impact
        const startTime = performance.now();
        const isEqual = oldData.metrics.length === newData.metrics.length;
        const endTime = performance.now();
        
        if (endTime - startTime > 1) {
          console.warn(`Slow comparison detected: ${endTime - startTime}ms`);
        }
        
        return isEqual;
      }
    }
  }
});

Memory Optimization ​

tsx
// Memory-efficient store configuration using Setup patterns
interface MemoryOptimizedUIStores extends UIStores {
  largeList: LargeItem[];
  circularData: any;
}

const {
  Provider: UIStoreProvider,
  useStore: useUIStore
} = createStoreContext<MemoryOptimizedUIStores>('UI', {
  // Standard UIStores fields
  modal: { isOpen: false, type: undefined, data: undefined },
  loading: { global: false, operations: {} },
  notifications: { items: [], maxVisible: 5 },
  navigation: { currentRoute: '', history: [], params: {} },
  
  // Memory-optimized fields
  largeList: {
    initialValue: [] as LargeItem[],
    strategy: 'reference' as const, // Avoid expensive deep comparisons
    comparisonOptions: {
      maxDepth: 1, // Limit comparison depth
      ignoreKeys: ['metadata', 'timestamps'] // Ignore non-essential data
    }
  },
  
  circularData: {
    initialValue: {} as any,
    comparisonOptions: {
      maxDepth: 3, // Prevent infinite recursion in circular references
      customComparator: (old, new_) => {
        // Handle circular references safely
        try {
          return JSON.stringify(old) === JSON.stringify(new_);
        } catch {
          return old === new_; // Fallback to reference comparison
        }
      }
    }
  }
});

Best Practices ​

  1. Follow Setup Patterns: Use established store interfaces from Basic Store Setup

    • UserStores: User profile, preferences, and session management
    • ProductStores: Product catalog, categories, filters, and shopping cart
    • UIStores: Modal, loading, notifications, and navigation state
    • FormStores: Form data, validation, and error handling
  2. Strategy Selection: Choose the most efficient comparison strategy

    • reference: For immutable data and large objects (ProductStores.catalog)
    • shallow: For simple objects with top-level changes (UserStores.profile)
    • deep: Only when necessary for nested objects (FormStores validation)
  3. Type Safety: Extend Setup patterns with proper TypeScript interfaces

    • Use interface ExtendedStores extends BaseStores for extensions
    • Maintain type consistency with Setup pattern definitions
  4. Ignore Irrelevant Keys: Use ignoreKeys for timestamp and metadata fields

    • Common pattern: ignoreKeys: ['timestamp', 'lastUpdated', 'sessionId']
  5. Custom Comparators: Implement domain-specific comparison logic

    • Performance optimization for large datasets
    • Business logic-based comparison for domain-specific needs
  6. Performance Monitoring: Use debug mode and timing in development

    • Enable debug for critical stores during development
    • Monitor comparison performance with custom comparators
  7. Memory Management: Set appropriate maxDepth for nested objects

    • Prevent infinite recursion with circular references
    • Optimize comparison depth based on data structure
  8. Production Optimization: Disable debug mode in production builds

    • Use environment-based debug configuration
    • Remove development-only logging and performance tracking

Common Configuration Patterns ​

tsx
// Real-world configuration examples using Setup patterns
// Combining UserStores and FormStores patterns from Setup guide
interface RealWorldStores {
  // From UserStores pattern
  userProfile: {
    id: string;
    name: string;
    email: string;
    role: 'admin' | 'user' | 'guest';
  };
  userPreferences: {
    theme: 'light' | 'dark';
    language: 'en' | 'ko' | 'ja' | 'zh';
    notifications: boolean;
    lastUpdated: number;
  };
  
  // From ProductStores pattern (for cache)
  dataCache: Map<string, any>;
  
  // From FormStores pattern (adapted)
  formState: {
    fields: Record<string, any>;
    validation: Record<string, boolean>;
    errors: Record<string, string>;
  };
}

const {
  Provider: RealWorldStoreProvider,
  useStore: useRealWorldStore
} = createStoreContext<RealWorldStores>('RealWorld', {
  // User data - shallow comparison for profile updates (UserStores pattern)
  userProfile: {
    initialValue: { id: '', name: '', email: '', role: 'guest' },
    strategy: 'shallow' as const
  },
  
  // UI preferences - ignore timestamps (UserStores pattern extended)
  userPreferences: {
    initialValue: { theme: 'light', language: 'en', notifications: true, lastUpdated: 0 },
    strategy: 'shallow' as const,
    comparisonOptions: { ignoreKeys: ['lastUpdated'] }
  },
  
  // Large dataset - reference equality for performance (ProductStores pattern)
  dataCache: {
    initialValue: new Map(),
    strategy: 'reference' as const
  },
  
  // Form state - deep comparison for nested validation (FormStores pattern)
  formState: {
    initialValue: { fields: {}, validation: {}, errors: {} },
    strategy: 'deep' as const,
    comparisonOptions: { maxDepth: 3 }
  }
});

Integration with Setup Patterns ​

This configuration guide builds on the foundation established in Basic Store Setup. Key integration points:

Type Reuse ​

  • Base Interfaces: Use UserStores, ProductStores, UIStores, and FormStores as foundation
  • Extension Pattern: Extend base interfaces for advanced configuration needs
  • Type Safety: Maintain consistency with Setup pattern type definitions

Configuration Alignment ​

  • Strategy Consistency: Apply configuration strategies to Setup pattern stores
  • Provider Naming: Follow standard naming conventions from Setup patterns
  • Context Integration: Align with Setup context creation and provider patterns

Best Practice Compliance ​

  • 90%+ Setup Compliance: All examples follow established Setup patterns
  • Reusable Configuration: Configuration options work with any Setup pattern store
  • Performance Optimization: Advanced features enhance Setup pattern performance

Released under the Apache-2.0 License.