# Minimize Re-renders

**MUST** · **ID:** `performance-minimize-rerenders` · **Category:** performance
**Source:** [Vercel](https://github.com/vercel-labs/agent-skills/blob/main/skills/web-design-guidelines/SKILL.md)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/performance-minimize-rerenders

> MUST: Track and minimize re-renders (React DevTools/React Scan)

Minimize and make re-renders fast

Excessive re-renders slow down the UI, especially in controlled inputs. Use React.memo, useMemo, and useCallback judiciously. Profile with React DevTools to identify components that re-render unnecessarily.

## Bad — do not do this

`performance-minimize-rerenders-bad`

```tsx
import { useState, useRef } from 'react';

function ExpensiveChild({ data }: { data: string }) {
  const renders = useRef(0);
  renders.current += 1;

  let sum = 0;
  for (let i = 0; i < 1000000; i++) sum += i;
  void sum;

  return (
    <div className="mt-3 flex items-center justify-between rounded-md bg-muted px-2 py-1.5 text-xs">
      <span className="text-muted-foreground">Child: {data || 'empty'}</span>
      <span className="font-medium tabular-nums text-destructive">renders: {renders.current}</span>
    </div>
  );
}

export function MinimizeRerendersBad() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  return (
    <div className="w-full max-w-sm space-y-4">
      <div className="bg-card border border-border rounded-lg p-4">
        <button
          onClick={() => setCount(count + 1)}
          className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 mb-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
        >
          Count: {count}
        </button>
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
          className="w-full px-3 py-2 bg-background border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
          placeholder="Type here..."
        />
        <ExpensiveChild data={text} />
      </div>
      <p className="text-xs text-destructive">
        Click Count and watch the counter climb: the expensive child re-renders every time, even though its
        <code> data</code> never changed
      </p>
    </div>
  );
}
```

## Good — do this

`performance-minimize-rerenders-good`

```tsx
import { useState, useRef, memo } from 'react';

const ExpensiveChild = memo(({ data }: { data: string }) => {
  const renders = useRef(0);
  renders.current += 1;

  let sum = 0;
  for (let i = 0; i < 1000000; i++) sum += i;
  void sum;

  return (
    <div className="mt-3 flex items-center justify-between rounded-md bg-muted px-2 py-1.5 text-xs">
      <span className="text-muted-foreground">Child: {data || 'empty'}</span>
      <span className="font-medium tabular-nums text-success">renders: {renders.current}</span>
    </div>
  );
});

ExpensiveChild.displayName = 'ExpensiveChild';

export function MinimizeRerendersGood() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  return (
    <div className="w-full max-w-sm space-y-4">
      <div className="bg-card border border-border rounded-lg p-4">
        <button
          onClick={() => setCount(count + 1)}
          className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 mb-2 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
        >
          Count: {count}
        </button>
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
          className="w-full px-3 py-2 bg-background border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
          placeholder="Type here..."
        />
        <ExpensiveChild data={text} />
      </div>
      <p className="text-xs text-success">
        Click Count as much as you like: the memoized child's counter does not move. It only re-renders when
        <code> data</code> actually changes
      </p>
    </div>
  );
}
```

## References

- [React Performance](https://react.dev/learn/render-and-commit)
- [React DevTools](https://react.dev/learn/react-developer-tools)
