Skip to content

noComponentHookFactories

biome.json
{
"linter": {
"rules": {
"nursery": {
"noComponentHookFactories": "error"
}
}
}
}

Disallows defining React components or custom hooks inside other functions.

Defining components or hooks inside other functions creates new instances on every call. React treats each new instance as a completely different component, which destroys and recreates the entire component subtree on each render and causes all state to be lost.

A component is defined inside a factory function:

function makeComponent(label) {
function MyComponent() {
return <div>{label}</div>;
}
return MyComponent;
}
code-block.jsx:2:12 lint/nursery/noComponentHookFactories ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Do not define component MyComponent inside a function.

1 │ function makeComponent(label) {
> 2 │ function MyComponent() {
^^^^^^^^^^^
3 │ return <div>{label}</div>;
4 │ }

React treats components defined inside functions as completely different on each call, destroying the entire subtree and losing all state. Move it to the module level.

This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

A hook is defined inside a factory function:

function makeHook(key) {
function useMyHook() {
return useState(key);
}
return useMyHook;
}
code-block.jsx:2:12 lint/nursery/noComponentHookFactories ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Do not define hook useMyHook inside a function.

1 │ function makeHook(key) {
> 2 │ function useMyHook() {
^^^^^^^^^
3 │ return useState(key);
4 │ }

Each call creates a new hook identity, causing React to lose its state across renders. Move it to the module level.

This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

Components and hooks defined at the module level:

function MyComponent() {
return <div>Hello</div>;
}
function useMyHook() {
return useState(0);
}

Higher-order components that receive a component as a parameter are allowed:

function withAuth(WrappedComponent) {
function AuthenticatedComponent(props) {
return <WrappedComponent {...props} />;
}
return AuthenticatedComponent;
}