Skip to content

Commit 4b71e30

Browse files
committed
docs: improve rule docs for setState in effect hooks
1 parent 2a3f1cb commit 4b71e30

File tree

2 files changed

+114
-16
lines changed

2 files changed

+114
-16
lines changed

packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-direct-set-state-in-use-effect.md

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,60 @@ react-hooks-extra/no-direct-set-state-in-use-effect
2828

2929
Disallow **direct** calls to the [`set` function](https://react.dev/reference/react/useState#setstate) of `useState` in `useEffect`.
3030

31-
This rule only checks for **direct** calls to the `set` function of `useState` in `useEffect`. It does not check for calls to `set` function in callbacks, event handlers, or `Promise.then` functions.
31+
Directly setting state in `useEffect` can lead to:
32+
33+
- **Redundant state**: You might be duplicating derived values that could be computed during render.
34+
- **Unnecessary effects**: Triggering re-renders that could be avoided.
35+
- **Confusing logic**: It can make component behavior harder to reason about.
36+
37+
### What counts as a violation?
38+
39+
This is **not allowed**:
40+
41+
```tsx
42+
useEffect(() => {
43+
setFullName(firstName + " " + lastName);
44+
}, [firstName, lastName]);
45+
```
46+
47+
Instead, compute the value during render:
48+
49+
```tsx
50+
const fullName = firstName + " " + lastName;
51+
```
52+
53+
### What is allowed?
54+
55+
The rule **does not flag** indirect calls, such as:
56+
57+
- Inside event handlers.
58+
- Inside `async` functions.
59+
- Inside `setTimeout`, `setInterval`, `Promise.then`, etc.
60+
61+
### Known limitations
62+
63+
- It doesn’t check `set` calls in `useEffect` cleanup functions.
64+
65+
```tsx {2}
66+
useEffect(() => {
67+
return () => {
68+
setFullName(firstName + " " + lastName); // ❌ Direct call
69+
};
70+
}, [firstName, lastName]);
71+
```
72+
73+
- It doesn’t detect `set` calls in `async` functions are being called before or after the `await` statement.
74+
75+
```tsx {2}
76+
useEffect(() => {
77+
const fetchData = async () => {
78+
setFullName(data.name); // ❌ Direct call
79+
};
80+
fetchData();
81+
}, []);
82+
```
83+
84+
These limitations may be addressed in the future.
3285

3386
## Examples
3487

@@ -246,13 +299,6 @@ function List({ items }) {
246299
}
247300
```
248301

249-
## Known limitations
250-
251-
- The `set` call to `useState` in the `cleanup` function of `useEffect` will not be checked.
252-
- The current implementation does not support determining whether a `set` function called in an `async` function is actually at least one `await` after.
253-
254-
The limitation may be lifted in the future.
255-
256302
## Implementation
257303

258304
- [Rule source](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-direct-set-state-in-use-effect.ts)

packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-direct-set-state-in-use-layout-effect.md

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,70 @@ react-hooks-extra/no-direct-set-state-in-use-layout-effect
1818

1919
`🧪`
2020

21+
**Presets**
22+
23+
- `recommended`
24+
- `recommended-typescript`
25+
- `recommended-type-checked`
26+
2127
## Description
2228

2329
Disallow **direct** calls to the [`set` function](https://react.dev/reference/react/useState#setstate) of `useState` in `useLayoutEffect`.
2430

25-
This rule only checks for **direct** calls to the `set` function of `useState` in `useEffect`. It does not check for calls to `set` function in callbacks, event handlers, or `Promise.then` functions.
31+
Directly setting state in `useLayoutEffect` can lead to:
32+
33+
- **Redundant state**: You might be duplicating derived values that could be computed during render.
34+
- **Unnecessary effects**: Triggering re-renders that could be avoided.
35+
- **Confusing logic**: It can make component behavior harder to reason about.
36+
37+
### What counts as a violation?
38+
39+
This is **not allowed**:
40+
41+
```tsx
42+
useLayoutEffect(() => {
43+
setFullName(firstName + " " + lastName);
44+
}, [firstName, lastName]);
45+
```
46+
47+
Instead, compute the value during render:
48+
49+
```tsx
50+
const fullName = firstName + " " + lastName;
51+
```
52+
53+
### What is allowed?
54+
55+
The rule **does not flag** indirect calls, such as:
56+
57+
- Inside event handlers.
58+
- Inside `async` functions.
59+
- Inside `setTimeout`, `setInterval`, `Promise.then`, etc.
60+
61+
### Known limitations
62+
63+
- It doesn’t check `set` calls in `useLayoutEffect` cleanup functions.
64+
65+
```tsx {2}
66+
useLayoutEffect(() => {
67+
return () => {
68+
setFullName(firstName + " " + lastName); // ❌ Direct call
69+
};
70+
}, [firstName, lastName]);
71+
```
72+
73+
- It doesn’t detect `set` calls in `async` functions are being called before or after the `await` statement.
74+
75+
```tsx {2}
76+
useLayoutEffect(() => {
77+
const fetchData = async () => {
78+
setFullName(data.name); // ❌ Direct call
79+
};
80+
fetchData();
81+
}, []);
82+
```
83+
84+
These limitations may be addressed in the future.
2685

2786
## Examples
2887

@@ -240,13 +299,6 @@ function List({ items }) {
240299
}
241300
```
242301

243-
## Known limitations
244-
245-
- The `set` call to `useState` in the `cleanup` function of `useLayoutEffect` will not be checked.
246-
- The current implementation does not support determining whether a `set` function called in an `async` function is actually at least one `await` after.
247-
248-
The limitation may be lifted in the future.
249-
250302
## Implementation
251303

252304
- [Rule source](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-hooks-extra/src/rules/no-direct-set-state-in-use-layout-effect.ts)

0 commit comments

Comments
 (0)