Skip to content

Commit a97f521

Browse files
committed
Add docs
1 parent aef4eaa commit a97f521

File tree

2 files changed

+90
-3
lines changed

2 files changed

+90
-3
lines changed

packages/eslint-plugin-react-hooks/README.md

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,93 @@ We suggest to use this option **very sparingly, if at all**. Generally saying, w
7171

7272
Please refer to the [Rules of Hooks](https://reactjs.org/docs/hooks-rules.html) documentation and the [Hooks FAQ](https://reactjs.org/docs/hooks-faq.html#what-exactly-do-the-lint-rules-enforce) to learn more about this rule.
7373

74-
## License
74+
## no-nested-components
7575

76-
MIT
76+
Based of [`react/no-unstable-nested-components`](https://github.com/jsx-eslint/eslint-plugin-react/blob/8beb2aae3fbe36dd6f495b72cb20b27c043aff68/docs/rules/no-unstable-nested-components.md) but with a [detection mechanism consistent with Rules of Hooks](https://reactjs.org/docs/hooks-faq.html#what-exactly-do-the-lint-rules-enforce).
77+
78+
Creating components inside components (nested components) will cause React to throw away the state of those nested components on each re-render of their parent.
79+
80+
React reconciliation performs element type comparison with [reference equality](https://reactjs.org/docs/reconciliation.html#elements-of-different-types). The reference to the same element changes on each re-render when defining components inside the render block. This leads to complete recreation of the current node and all its children. As a result the virtual DOM has to do extra unnecessary work and [possible bugs are introduced](https://codepen.io/ariperkkio/pen/vYLodLB).
81+
82+
### `no-nested-components` details
83+
84+
The following patterns are considered warnings:
85+
86+
```jsx
87+
function Component() {
88+
// nested component declaration
89+
function UnstableNestedComponent() {
90+
return <div />;
91+
}
92+
93+
return (
94+
<div>
95+
<UnstableNestedComponent />
96+
</div>
97+
);
98+
}
99+
```
100+
101+
102+
```jsx
103+
function useComponent() {
104+
// Nested component declaration in a hook. See https://reactjs.org/docs/hooks-faq.html#what-exactly-do-the-lint-rules-enforce for what's considered a Component and hook.
105+
return function Component() {
106+
return <div />
107+
}
108+
}
109+
```
110+
111+
```jsx
112+
function Component() {
113+
const config = React.useMemo({
114+
// Nested component declaration. See https://reactjs.org/docs/hooks-faq.html#what-exactly-do-the-lint-rules-enforce for what's considered a component.
115+
ArrowDown(event) {
116+
117+
}
118+
})
119+
120+
return (
121+
<div>
122+
<UnstableNestedComponent />
123+
</div>
124+
);
125+
}
126+
```
127+
128+
129+
The following patterns are **not** considered warnings:
130+
131+
```jsx
132+
function OutsideDefinedComponent(props) {
133+
return <div />;
134+
}
135+
136+
function Component() {
137+
return (
138+
<div>
139+
<OutsideDefinedComponent />
140+
</div>
141+
);
142+
}
143+
```
144+
145+
⚠️ WARNING ⚠️:
146+
147+
Creating nested but memoized components should also be avoided since memoization is a performance concern not a semantic guarantee.
148+
If the `useCallback` or `useMemo` hook has no dependency, you can safely move the component definition out of the render function.
149+
If the hook does have dependencies, you should refactor the code so that you're able to move the component definition out of the render function.
150+
If you want React to throw away the state of the nested component, use a [`key`](https://reactjs.org/docs/lists-and-keys.html#keys) instead.
151+
152+
```jsx
153+
function Component() {
154+
// No ESLint warning but `MemoizedNestedComponent` should be moved outside of `Component`.
155+
const MemoizedNestedComponent = React.useCallback(() => <div />, []);
156+
157+
return (
158+
<div>
159+
<MemoizedNestedComponent />
160+
</div>
161+
);
162+
}
163+
```

packages/eslint-plugin-react-hooks/src/NoNestedComponents.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export default {
128128
docs: {
129129
description: 'Ensures all component definitions ensure persistent state.',
130130
recommended: true,
131-
url: 'https://reactjs.org/docs/??',
131+
url: 'https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks#no-nested-components',
132132
},
133133
messages: {
134134
declarationDuringRender:

0 commit comments

Comments
 (0)