This repository contains React 17 examples demonstrating different state management approaches and performance characteristics. Created to explore and compare various store implementation patterns.
A side-by-side comparison of two different state management approaches:
- JavaScript Proxy-based state management
- Automatic change detection via Proxy traps
- Direct property assignment support (
store.count = 5) - Method calls and direct mutations both work
- Singleton pattern for global state consistency
Pros:
- Simple API - just modify the store object directly
- No boilerplate code needed
- Works with both method calls and direct property assignment
- Automatic change detection
Cons:
- Not compatible with React 18 concurrent mode
- Creates new functions on every access (performance issues)
- No automatic update batching
- Breaks React's dependency arrays
- Memory overhead from Proxy and function wrapping
- React's built-in state management solution
- Provider/Consumer pattern with hooks
- Explicit setter functions required
- Unidirectional data flow following React patterns
Pros:
- Built into React, no external dependencies
- Fully supports React 18 concurrent mode
- Predictable updates and data flow
- Full React DevTools support
- Automatic update batching in React 18
Cons:
- Requires provider setup and context creation
- All consumers re-render on any state change
- Must use setter functions, no direct assignment
- More complex setup for simple state management
Interactive Sierpiński Triangle example demonstrating React 17's synchronous rendering performance issues:
- Heavy computation simulation with configurable CPU time per component
- Exponential complexity - triangle count grows as 3^depth
- Interactive controls for depth and CPU time adjustment
- Real-time performance metrics showing render times and component counts
- Animation system that continuously triggers re-renders
- UI blocking demonstration - try to interact during heavy renders!
src/
├── components/ # Reusable UI components
│ ├── FeatureSelector/ # Main navigation component
│ ├── StoreComparison/ # Store comparison demo
│ ├── ProxyStoreDemo/ # Proxy store implementation
│ ├── ContextAPIDemo/ # Context API implementation
│ ├── GranularComponents/ # Individual count/text components
│ └── SierpinskiTriangle/ # Triangle rendering component
├── examples/ # Complete demo examples
│ └── SierpinskiTriangleExample/ # Performance demo
├── stores/ # Store implementations
│ ├── proxyStore.ts # Proxy-based store
│ ├── proxyWrapper.ts # Generic proxy wrapper
│ ├── contextAPIStore.tsx # Context API store
│ └── index.ts # Store exports
└── constants/ # Shared constants
- Node.js (v14 or higher)
- npm or yarn
# Clone the repository
git clone <repository-url>
cd react-happy-2020
# Install dependencies
npm install
# Start development server
npm startOpen http://localhost:3000 to view the demo in your browser.
- Select "Store Comparison" from the navigation
- Interact with both sides - increment counters, generate random text
- Watch the console for re-render patterns:
[PROXY]logs show proxy store activity[CONTEXT]logs show context API activity
- Notice granularity issues - both components re-render on any change
- Select "React 17 Performance" from the navigation
- Adjust settings:
- Recursion Depth: 1-7 (controls triangle count: 3^depth)
- CPU Time per Triangle: 0-5ms (simulates heavy computation)
- Start animation to see continuous re-renders
- Try to interact with the page during animation
- Observe blocking behavior - UI becomes unresponsive with high settings
- Light load: Depth 3, CPU time 0.5ms
- Medium load: Depth 4, CPU time 1ms
- Heavy load: Depth 5+, CPU time 2ms+ (
⚠️ Will block UI!)
- Proxy Store Issues: While convenient, has React 18 compatibility problems
- Context API Benefits: React-native solution with better future compatibility
- Granularity Problems: Both approaches have re-render granularity issues by default
- React 17 Limitations: Synchronous rendering blocks user interactions
- Performance Impact: Heavy computations can completely freeze the UI
Runs the app in development mode at http://localhost:3000
Launches the test runner in interactive watch mode
Builds the app for production to the build folder
Note: This is a one-way operation! Ejects from Create React App configuration.
