Skip to main content
interlace
Plugin: react-featuresRules

no-multi-comp

no-multi-comp rule

no-multi-comp rule

Prevent multiple component definitions per file. This rule is part of eslint-plugin-react-features.

Quick Summary

AspectDetails
SeverityWarning (organization)
Auto-Fix❌ No (requires file extraction)
CategoryReact
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForReact projects with strict organization

Rule Details

Each React component should be in its own file for better maintainability, testing, and code organization. This follows the single responsibility principle.

Why This Matters

IssueImpactSolution
🔄 Hard to findComponents hidden in large filesOne component per file
🐛 Testing difficultyHard to isolate testsSeparate files enable mocks
🔍 Merge conflictsMultiple devs editing same fileSeparate ownership

Examples

❌ Incorrect

// UserComponents.tsx - BAD: Multiple components in one file
function UserAvatar({ src, alt }) {
  return <img src={src} alt={alt} className="avatar" />;
}

function UserName({ name }) {
  return <span className="username">{name}</span>;
}

function UserCard({ user }) {
  return (
    <div className="user-card">
      <UserAvatar src={user.avatar} alt={user.name} />
      <UserName name={user.name} />
    </div>
  );
}

export default UserCard;

✅ Correct

// UserCard.tsx — one component; helpers that are not components are fine
function renderBadge(role: string) {
  return <span className="badge">{role}</span>;
}

export default function UserCard({ user }) {
  return (
    <div className="user-card">
      {user.name} {renderBadge(user.role)}
    </div>
  );
}

A component, as React defines one: a class that extends React's Component / PureComponent, a function whose name starts with a capital letter and that returns JSX, or a function passed to React's memo / forwardRef. A lowercase render helper or a PascalCase function that returns no JSX is not a component. Every component after the first is reported; with ignoreStateless: true, only class components count.

Options

OptionTypeDefaultDescription
ignoreStatelessbooleanfalseAllow multiple stateless functional components

Configuration with Options

{
  rules: {
    'react-features/no-multi-comp': ['warn', {
      ignoreStateless: true  // Allow small helper components
    }]
  }
}

Configuration Examples

Basic Usage

{
  rules: {
    'react-features/no-multi-comp': 'warn'
  }
}

Strict Usage

{
  rules: {
    'react-features/no-multi-comp': 'error'
  }
}

Further Reading

Known False Negatives

  • Components made by other higher-order functions: styled.div, connect(...)(View) or a custom withX(() => <div />) are not counted; only memo / forwardRef (by binding), PascalCase functions that return JSX, and classes that extend React's Component / PureComponent are.
  • A component that returns JSX only through a helper call (function Card() { return renderCard(); }) is not recognised.

Use this rule

npm install -D oxlint-plugin-react-features
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-react-features"],  "rules": {    "react-features/no-multi-comp": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-react-features'],    rules: {      'react-features/no-multi-comp': 'error',    },  },});

oxlint-plugin-react-features re-exports eslint-plugin-react-features/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.