Skip to main content
ESLint Interlace
Plugin: react-featuresRules

require-optimization

require-optimization rule

Keywords: React, performance, memo, useMemo, useCallback, optimization, re-renders, ESLint rule, LLM-optimized

Suggest performance optimizations for React components based on usage patterns. This rule is part of eslint-plugin-react-features.

Quick Summary

AspectDetails
SeveritySuggestion (performance)
Auto-Fix❌ No (requires manual optimization)
CategoryReact
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForReact applications needing performance tuning

Rule Details

Analyzes React components and suggests appropriate optimizations based on their structure, props count, and usage patterns.

Why This Matters

IssueImpactSolution
🔄 Unnecessary re-rendersPoor performanceUse React.memo
🐛 Expensive computationsSlow rendersUse useMemo
🔍 Function recreationChild component re-rendersUse useCallback

Optimization Messages

Message IDWhen SuggestedOptimization
considerMemoComponent has many propsWrap with React.memo()
considerUseMemoContains array operationsWrap computation with useMemo()
considerUseCallbackInline event handlersWrap with useCallback()
considerLazyLarge component (50+ lines)Use React.lazy()
considerPureComponentClass component with many propsExtend PureComponent

Examples

❌ Unoptimized

// Component with many props - may benefit from memo
function UserCard({ name, email, avatar, role, status, onClick, onEdit }) {
  // Expensive computation on every render
  const permissions = roles.map(r => getPermissions(r)).flat();
  
  // Inline function recreated every render
  return (
    <Card onClick={() => onClick(name)}>
      <Avatar src={avatar} />
      <div>{name}</div>
      <div>{email}</div>
    </Card>
  );
}

// Class component that could be PureComponent
class DataTable extends React.Component {
  render() {
    const { data, columns, sortBy, filterBy, onSort, onFilter } = this.props;
    return <Table data={data} columns={columns} />;
  }
}

✅ Optimized

// GOOD: Memoized component with many props
const UserCard = React.memo(function UserCard({ 
  name, email, avatar, role, status, onClick, onEdit 
}) {
  // GOOD: Expensive computation memoized
  const permissions = useMemo(
    () => roles.map(r => getPermissions(r)).flat(),
    [roles]
  );
  
  // GOOD: Callback memoized
  const handleClick = useCallback(() => {
    onClick(name);
  }, [onClick, name]);
  
  return (
    <Card onClick={handleClick}>
      <Avatar src={avatar} />
      <div>{name}</div>
      <div>{email}</div>
    </Card>
  );
});

// GOOD: Using PureComponent for shallow comparison
class DataTable extends React.PureComponent {
  render() {
    const { data, columns, sortBy, filterBy, onSort, onFilter } = this.props;
    return <Table data={data} columns={columns} />;
  }
}

// GOOD: Large component with code splitting
const Dashboard = React.lazy(() => import('./Dashboard'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <Dashboard />
    </Suspense>
  );
}

Options

OptionTypeDefaultDescription
suggestMemobooleantrueSuggest React.memo for components
suggestUseMemobooleantrueSuggest useMemo for expensive computations
suggestUseCallbackbooleantrueSuggest useCallback for event handlers
minPropsForMemonumber3Minimum props count to suggest memo

Configuration with Options

{
  rules: {
    'react-features/require-optimization': ['warn', {
      suggestMemo: true,
      suggestUseMemo: true,
      suggestUseCallback: true,
      minPropsForMemo: 5  // More conservative threshold
    }]
  }
}

Configuration Examples

Basic Usage

{
  rules: {
    'react-features/require-optimization': 'warn'
  }
}

Conservative (fewer suggestions)

{
  rules: {
    'react-features/require-optimization': ['warn', {
      minPropsForMemo: 6,
      suggestUseCallback: false  // Only for critical paths
    }]
  }
}

Further Reading

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Dynamic Variable References

Why: Static analysis cannot trace values stored in variables or passed through function parameters.

// ❌ NOT DETECTED - Prop from variable
const propValue = computedValue;
<Component prop={propValue} /> // Computation not analyzed

Mitigation: Implement runtime validation and review code manually. Consider using TypeScript branded types for validated inputs.

Cross-Module Data Flow

Why: ESLint rules analyze one file at a time. Values imported from other modules cannot be traced.

// ❌ NOT DETECTED - Value from import
import { getValue } from './helpers';
processValue(getValue()); // Cross-file not tracked

Mitigation: Apply the same rule to imported modules. Use module boundaries and explicit exports.