Skip to content

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:

  1. Check component props with React DevTools
  2. Verify prop equality comparisons
  3. Use the monitoring tools to track render patterns
  4. Consider splitting components further

Memory Management

To prevent memory leaks:

  1. Clean up effects properly
  2. Unsubscribe from subscriptions
  3. Clear intervals and timeouts
  4. 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

Released under the MIT License.