Skip to content

no-god-components

Report React components that have grown past the limits this rule sets.

This rule checks function components whose names start with an uppercase letter. It also checks components wrapped in memo or forwardRef.

By default it reports these cases:

  • more than 200 lines in a component
  • more than 120 lines when enforceTargetLines is true
  • more than 5 destructured props in the first parameter
  • more than 3 levels of JSX or TSX nesting
  • more than 5 state hook calls, counting useState, useReducer, and useBinding
  • any runtime null literal inside the component body

Nested functions do not count toward JSX depth or hook usage. null literal type annotations are ignored.

eslint.config.ts
import plugin from "eslint-plugin-cease-nonsense";
export default [
{
plugins: { "cease-nonsense": plugin },
rules: {
"cease-nonsense/no-god-components": [
"error",
{
maxLines: 180,
targetLines: 100,
maxDestructuredProps: 4,
maxTsxNesting: 2,
maxStateHooks: 4,
stateHooks: ["useState", "useReducer", "useBinding"],
ignoreComponents: ["App"],
},
],
},
},
];

Options and defaults:

  • enforceTargetLines, default true
  • targetLines, default 120
  • maxLines, default 200
  • maxDestructuredProps, default 5
  • maxTsxNesting, default 3
  • maxStateHooks, default 5
  • stateHooks, default ['useState', 'useReducer', 'useBinding']
  • ignoreComponents, default []
Incorrect
function Dashboard({ a, b, c, d, e, f }) {
const [user, setUser] = useState();
const [theme, setTheme] = useState();
const [notifications, setNotifications] = useState([]);
const [data, setData] = useState();
const [filter, setFilter] = useState('');
const [sort, setSort] = useReducer(reducer, initialState);
return (
<div>
<section>
<div>
<span>{null}</span>
</div>
</section>
</div>
);
}
Correct
function Dashboard() {
const { user, notifications } = useDashboardData();
const filters = useDashboardFilters();
return (
<Layout>
<Header user={user} />
<MainContent data={notifications} filters={filters} />
</Layout>
);
}