# react-hooks/set-state-in-render

> Disallow calling a state setter unconditionally while a component renders

Setting state makes React render the component again. If the component sets state every time it renders, it never stops, and React gives up with "Too many re-renders".

The rule reports a setter that's always called during render, directly or through a function the component calls. It also reports every setter called in a `useMemo()` callback. It doesn't report a setter behind a condition, or one in an event handler or an effect.

{/* 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-hooks/set-state-in-render" = "error" # or "warn"
```

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

## Examples

Reported:

{/* bad */}
```jsx
import { useState } from "react";

function Cart({ items }) {
  const [count, setCount] = useState(0);
  setCount(items.length);
  return <span>{count}</span>;
}
```

A `useMemo()` callback runs during render too:

{/* bad */}
```jsx
import { useMemo, useState } from "react";

function Cart({ items }) {
  const [count, setCount] = useState(0);
  const total = useMemo(() => {
    setCount(items.length);
    return items.reduce((sum, item) => sum + item.price, 0);
  }, [items]);
  return <span>{count} items, {total}</span>;
}
```

Not reported:

{/* good */}
```jsx
function Cart({ items }) {
  const count = items.length;
  return <span>{count}</span>;
}
```

{/* good */}
```jsx
import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
```

A setter behind a condition is how you reset state when a prop changes. The condition is false on the next render, so the loop ends:

{/* good */}
```jsx
import { useState } from "react";

function List({ items }) {
  const [previous, setPrevious] = useState(items);
  const [selected, setSelected] = useState(null);
  if (items !== previous) {
    setPrevious(items);
    setSelected(null);
  }
  return <ul onClick={() => setSelected(0)}>{selected}</ul>;
}
```
