Best Practices Guide
This guide covers recommended patterns and practices when using ZenReact to optimize your React applications.
Component Optimization
When to Use withOptimization
Use withOptimization
when your component:
- Receives complex props that are expensive to compare
- Re-renders frequently due to parent updates
- Performs expensive computations or renders
- Is used in a list or grid with many items
jsx
// Good: Complex data props
const UserProfile = withOptimization(({ user, permissions, settings }) => {
// Component logic...
});
// Good: Expensive rendering
const DataGrid = withOptimization(({ rows, columns }) => {
// Complex grid rendering...
});
// Not necessary: Simple props
const Button = ({ onClick, children }) => <button onClick={onClick}>{children}</button>;
Component Structure
- Keep components focused and single-purpose
- Split large components into smaller, optimized pieces
- Use composition to build complex UIs
jsx
// Better: Split into focused components
const UserCard = withOptimization(({ user }) => (
<div>
<UserAvatar user={user} />
<UserInfo user={user} />
<UserActions user={user} />
</div>
));
// Instead of one large component
const UserCard = ({ user, permissions, settings, actions }) => {
// Too many responsibilities...
};
State Management
Effective Use of useOptimizedState
useOptimizedState
works best for:
- Form inputs with frequent updates
- Search inputs that trigger API calls
- Real-time data updates
- Animation states
jsx
// Good: Search with API calls
function SearchComponent() {
const [query, setQuery] = useOptimizedState('');
useEffect(() => {
// Auto-debounced API calls
searchAPI(query);
}, [query]);
return <input value={query} onChange={(e) => setQuery(e.target.value)} />;
}
// Good: Real-time updates
function LiveData() {
const [data, setData] = useOptimizedState([]);
// Updates are automatically batched
useEffect(() => {
socket.on('update', setData);
}, []);
return <DataView data={data} />;
}
State Structure
- Keep state minimal and focused
- Split complex state into manageable pieces
- Use appropriate data structures for your use case
jsx
// Better: Split focused state
const [searchQuery, setSearchQuery] = useOptimizedState('');
const [filters, setFilters] = useOptimizedState({});
const [sortOrder, setSortOrder] = useOptimizedState('asc');
// Instead of one large state object
const [tableState, setTableState] = useState({
search: '',
filters: {},
sort: 'asc',
// ...more properties
});
Performance Monitoring
Using @zenreact/monitor
Monitor your application's performance to identify optimization opportunities:
jsx
import { setupMonitor } from '@zenreact/monitor';
// Setup monitoring in development
if (process.env.NODE_ENV === 'development') {
setupMonitor({
logLevel: 'verbose',
trackComponents: true,
trackStateUpdates: true,
});
}
Key Metrics to Watch
- Component render times
- Re-render frequency
- State update patterns
- Props change patterns
Testing
Testing Optimized Components
When testing components using ZenReact optimizations:
jsx
// Test optimization behavior
it('should prevent unnecessary re-renders', () => {
const { rerender } = render(<OptimizedComponent data={data} />);
// First render
expect(screen.getByText('content')).toBeInTheDocument();
// Re-render with same data
rerender(<OptimizedComponent data={data} />);
// Check that internal content hasn't been re-rendered
expect(screen.getByText('content')).toBeInTheDocument();
});
Code Splitting
Using @zenreact/bundle
Optimize your bundle size:
jsx
import { lazy } from '@zenreact/bundle';
// Automatically optimized code splitting
const HeavyComponent = lazy(() => import('./HeavyComponent'), {
preload: true,
fallback: <LoadingSpinner />,
});
Server-Side Optimization
Using @zenreact/server
Optimize server-rendered React applications:
jsx
import { optimizeServer } from '@zenreact/server';
// Setup server optimization
optimizeServer({
caching: true,
compression: true,
preloadComponents: ['CriticalComponent'],
});
Common Issues
Debugging Re-Render Issues
If you notice unnecessary re-renders:
- Check component props with React DevTools
- Verify prop equality comparisons
- Use the monitoring tools to track render patterns
- Consider splitting components further
Memory Management
To prevent memory leaks:
- Clean up effects properly
- Unsubscribe from subscriptions
- Clear intervals and timeouts
- Dispose of heavy resources
jsx
useEffect(() => {
const subscription = subscribe();
return () => {
// Proper cleanup
subscription.unsubscribe();
};
}, []);
Additional Tips
- Start with the simplest optimization and measure its impact
- Use the monitoring tools to guide optimization efforts
- Focus on user-facing performance first
- Test optimizations across different devices and network conditions