diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md b/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md
index c8cfa22a027..d5bd4f82abf 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md
@@ -5,7 +5,7 @@ version: rc
-Validates against setting state during render, which can trigger additional renders and potential infinite render loops.
+Validates against unconditionally setting state during render, which can trigger additional renders and potential infinite render loops.
@@ -19,14 +19,14 @@ You can try it by upgrading the lint plugin [to the most recent RC version](/lea
## Rule Details {/*rule-details*/}
-Calling `setState` during render triggers another render before the current one finishes. This creates an infinite loop that crashes your app.
+Calling `setState` during render unconditionally triggers another render before the current one finishes. This creates an infinite loop that crashes your app.
## Common Violations {/*common-violations*/}
### Invalid {/*invalid*/}
```js {expectedErrors: {'react-compiler': [4]}}
-// ❌ setState directly in render
+// ❌ Unconditional setState directly in render
function Component({value}) {
const [count, setCount] = useState(0);
setCount(value); // Infinite loop!
@@ -59,6 +59,19 @@ function Component({user}) {
const email = user?.email || '';
return
{name}
;
}
+
+// ✅ Conditionally derive state from props and state from previous renders
+function Component({ items }) {
+ const [isReverse, setIsReverse] = useState(false);
+ const [selection, setSelection] = useState(null);
+
+ const [prevItems, setPrevItems] = useState(items);
+ if (items !== prevItems) { // This condition makes it valid
+ setPrevItems(items);
+ setSelection(null);
+ }
+ // ...
+}
```
## Troubleshooting {/*troubleshooting*/}
@@ -102,3 +115,5 @@ function Counter({max}) {
```
Now the setter only runs in response to the click, React finishes the render normally, and `count` never crosses `max`.
+
+In rare cases, you may need to adjust state based on information from previous renders. For those, follow [this pattern](https://react.dev/reference/react/useState#storing-information-from-previous-renders) of setting state conditionally.