# perf\(web\): Shift re-renders only each row's quick-action group · PR \#22726 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/22726)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: refactor/split-pull-requests-speed-mode

Target branch: refactor/split-pull-requests-thin-route

Head commit: 0290927ccadf16aca93b4ba8349222209c6e6302

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/22726)

[Commits](https://git.cafe/pingdotgg/t3code/pull/22726/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/22726/diffs?format=markdown)

## Description

---

Tapping Shift on the pull requests list cost about 15k renders. `speedMode` was a row prop, so every Shift press re-rendered every row along with its tooltips, buttons and icons, only to toggle `display` on the quick-action group.

Shift now reaches the rows through `PullRequestSpeedModeContext`. `PullRequestListGroups` provides it (`PullRequestSpeedModeProvider` holds the only key subscription), and a small `SpeedModeGroup` wrapper inside `PullRequestSpeedActions` is the only consumer. Rows are `memo`, so they bail out; the buttons are the wrapper's children, so they bail out too. Only the wrapper re-renders, one per row with quick actions. The thread panel's pull request list provides the same context from the Shift state it already tracks, so it behaves as before.

I first tried a `useShortcutModifierState` call in each wrapper. It cut renders the same way but raised commits from ~20 to ~820. Each row's window listener runs in its own task, so React committed once per row. The single provider keeps it to one commit per key change.

**Shift tapped 3 times, 136 rows listed** (rc-init render counter, dev server seeded from real data, fresh browser per side, base `6a6c84f990` vs this layer):

| | run 1 | run 2 | run 3 | median |
|---|---|---|---|---|
| main renders | 18,246 | 15,005 | 15,140 | **15,140** |
| after renders | 4,429 | 1,092 | 1,045 | **1,092** (-93%) |
| main commits | 22 | 23 | 22 | 22 |
| after commits | 18 | 18 | 13 | 18 |

Run 1 on both sides includes rows refreshing as the list data settles after load. After the change, the Shift renders are 816 `SpeedModeGroup` (136 rows × 6 key transitions) plus the sidebar, which listens to modifiers on its own.

Tests run: `tsc --noEmit` for apps/web, `vp lint` on the changed files, `vp test run src/reactCompilerCoverage.test.ts -t pullRequest` (0 bailouts).

Part of the pull request page split stack: #22671 → #22672 → #22702 → #22703 → #22704 → #22705 → #22706 → #22726 → #22727.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

