# Find what re-renders

The Renders tab counts every re-render in your app as it happens: which components re-render most, what set each burst off, which context providers re-render their consumers for nothing, and when something is stuck in a render loop.

You need your app running with the Squiggle SDK and connected to Studio. Render times come from React’s profiler, which only development and profiling builds include: a release build shows how often things re-render, but no times.

## Find the components that re-render most

Open the **Inspector** and choose **Renders**. The numbers along the top count since you last pressed **Reset**, and the chart plots renders per second. Drag its crosshair back to read a spike you missed. Under it, **Components** lists every component that re-rendered, hottest first. A component’s first render doesn’t count, only the ones after it.

| Column | What it shows |
| --- | --- |
| Component | Its name, and the file and line it is written at. |
| Last 30 s | Its re-renders per second, as a small bar chart. |
| Re-renders | How many times it re-rendered. |
| Per sec | How fast it is re-rendering right now. |
| Last · Total | How long its latest render took, and all of them together. |
| Why | What changed: the props by name, its state or a hook, or a context it reads. |

Click a column heading to sort by it. Hover a row for everything known about the component, and click it to select the component in the tree and outline it on the device.

To count only part of the app, select a component in the tree: the tab then counts what renders under it, and the chip in its header says **Under** and the component’s name. Clear it to count the whole app again. **On device** colours the components on the device by the same measure.

### Two warnings in the Why column

- **memo miss**: Its parent passed new props with the same values. Wrapping the component in `memo` would most likely have skipped the render.
- **new context value**: A context it reads got a new object with the same contents. Fix the provider; see [below](https://squiggle.sh/docs/inspector/renders#fix-a-provider-that-re-renders-its-consumers).

### What the colours mean

Green is calm and red is hot, the same in the tree, this list and the device’s Renders overlay. **Colour by** picks the measure: **Re-renders** (how many times), **Per second** (how fast right now) or **Either** (whichever is hotter).

## Find what started a burst

**Cascades** lists each burst of re-renders that reached more than one component, newest first. Each one names the topmost component that re-rendered, how many components and renders it spread to, and what set it off:

- a gesture, with the control it landed on: **Tap on “Add to cart”**
- a change to a store a component reads
- a context changing
- new props from above
- the component’s own state or a hook

Click a cascade to select the component it started at. The list keeps the latest 50.

## Catch a render loop

A component that keeps re-rendering with nothing happening is usually a loop: something it renders changes what it reads. When one re-renders at least as fast as **Loops** says (20 a second unless you change it) for three seconds in a row, the tab shows a banner and Studio sends a notification. **Select** on the banner, or **Show** on the notification, selects the component.

A loop that takes a whole subtree with it gives one notification, for its topmost component, with the number of components under it. You get another only after it has calmed down and started again. To catch a slower loop, choose 10 a second; to quiet a screen that animates on purpose, choose 30 or 60.

Studio watches for loops while the Inspector is open.

## Fix a provider that re-renders its consumers

A context provider that builds its value inline hands down a new object on every render, even when nothing in it changed. Every component that reads the context re-renders with it. **Providers** lists those providers with the components each one re-rendered for nothing, and those components carry **new context value** in **Components**. The fix is to keep the value the same object until its contents change:

```ts
// A new object on every render: every component that reads CartContext
// re-renders whenever CartProvider does.
<CartContext.Provider value={{ items, addItem }}>

// The same object until items or addItem changes.
const addItem = useCallback((item: Item) => setItems((all) => [...all, item]), []);
const value = useMemo(() => ({ items, addItem }), [items, addItem]);
<CartContext.Provider value={value}>
```

A provider whose value really changes is not listed: its consumers re-render for a reason.

## Hand it to your agent

**Copy prompt** copies the hottest components, their reasons and where they are written, ready to paste into a coding agent. An agent connected over MCP reads the same counts, cascades, loops and providers itself with the `renders` tool; see [Agent tools](https://squiggle.sh/docs/agents/tools).

## When something looks wrong

- **The list is empty**: Nothing has re-rendered since you pressed **Reset**, or under the component you selected. Use the app, or clear the selection.
- **A row says “call site unknown”**: The component comes from a library, or from code built without source locations, so Squiggle can’t say where it is written. Its parent row usually can.
- **Times are missing**: The app is a release build. Counts still work.
- **No notification for a component you can see looping**: It is re-rendering slower than **Loops**, or the Inspector isn’t open. Choose a lower rate.

> **Only Studio's view resets**
>
> **Reset** zeroes the counts in Studio. It doesn’t change your app, a recording, or the performance data Squiggle stores.
