# react/no-unstable-nested-components

> Disallow defining a component inside another component

A component defined inside another component is a new function every time the parent renders. React compares components by identity, so it sees a different component each time. It removes the old DOM nodes, builds new ones, and throws away the state of everything below. Inputs lose focus and their text, and effects run again.

Move the inner component to the top level of the file and pass it what it needs as props.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"react/no-unstable-nested-components" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"react/no-unstable-nested-components" = ["error", {
  allowAsProps = false,
  propNamePattern = "render*",
  customValidators = [], # list of strings
}]
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad */}
```jsx
function UserList({ users }) {
  function Row({ user }) {
    return <li>{user.name}</li>;
  }

  return (
    <ul>
      {users.map(user => (
        <Row key={user.id} user={user} />
      ))}
    </ul>
  );
}
```

A component created in a prop is reported too:

{/* bad */}
```jsx
function Page() {
  return <Layout footer={() => <small>Terms of use</small>} />;
}
```

Not reported:

{/* good */}
```jsx
function Row({ user }) {
  return <li>{user.name}</li>;
}

function UserList({ users }) {
  return (
    <ul>
      {users.map(user => (
        <Row key={user.id} user={user} />
      ))}
    </ul>
  );
}
```

A function passed as `children`, or in a prop whose name starts with `render`, counts as a render prop. The receiver calls it as a plain function, so nothing is remounted:

{/* good */}
```jsx
function Page() {
  return <Layout renderFooter={() => <small>Terms of use</small>} />;
}
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `allowAsProps` | `false` | Allow a component that's created in a prop. |
| `propNamePattern` | `"render*"` | A glob that matches the names of render props. |
| `customValidators` | `[]` | Accepted, but has no effect. |

{/* good {"options": [{"allowAsProps": true}]} */}
```jsx
function Page() {
  return <Layout footer={() => <small>Terms of use</small>} />;
}
```

{/* good {"options": [{"propNamePattern": "*Renderer"}]} */}
```jsx
function Report({ rows }) {
  return <Table rows={rows} rowRenderer={row => <Row data={row} />} />;
}
```
