Skip to content

💸 Perf - Early-return ButtonRow before its layout-measuring hooks - #4919

Draft
isaaclombardssw wants to merge 1 commit into
mainfrom
perf/4900-buttonrow-early-return
Draft

💸 Perf - Early-return ButtonRow before its layout-measuring hooks#4919
isaaclombardssw wants to merge 1 commit into
mainfrom
perf/4900-buttonrow-early-return

Conversation

@isaaclombardssw

Copy link
Copy Markdown
Member

Closes #4900

ButtonRow called useResizeObserver and read clientWidth on every mount because the data.buttons?.length > 0 check lived in the returned JSX, after the hooks. On the AI for Business Leaders page, 13 of the 14 button rows carry no buttons yet each still spun up a ResizeObserver and performed layout reads for a row that renders nothing.

Change

Split the component in two, keeping hooks unconditional (Rules of Hooks):

  • Outer ButtonRow does the cheap empty check and returns null before any hooks when data.buttons is empty.
  • New ButtonRowInner owns all the layout-measuring hooks (useResizeObserver, the refs, measure) and only mounts when there are buttons — so its hooks always run in the same order.

The full-width-button measuring logic is unchanged; the redundant data.buttons?.length > 0 && JSX guard was dropped since the outer guard already guarantees a non-empty array.

Verification

  • npx eslint on the changed file — clean (react-hooks/rules-of-hooks and exhaustive-deps both pass).
  • npx prettier --check — clean.
  • npx tsc --noEmit (with the Tina client generated locally) — no new errors.

Acceptance criteria: no ResizeObserver/layout reads when there are no buttons ✅; full-width behaviour preserved where buttons exist ✅; no hooks-order warnings ✅. The full-width behaviour on the hero block at mobile/desktop widths is worth a quick human eyeball since it wasn't runtime-tested here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q8genJyZboXaa4vgYhJF4P

ButtonRow ran useResizeObserver and layout reads unconditionally because the
empty check lived in the returned JSX, not before the hooks. On the AI for
Business Leaders page 13 of 14 button rows have no buttons yet still created a
ResizeObserver.

Split into an outer ButtonRow that returns null before any hooks when there are
no buttons, delegating the measuring logic to a new ButtonRowInner that owns all
the hooks and only mounts when buttons exist. Keeps hooks unconditional (Rules of
Hooks) and preserves the full-width-button behaviour unchanged.

Closes #4900

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q8genJyZboXaa4vgYhJF4P
@github-actions

Copy link
Copy Markdown
Contributor

Coverage report

St.
Category Percentage Covered / Total
🔴 Statements 0.57% 267/46820
🔴 Branches 9.9% 52/525
🔴 Functions 1.27% 6/474
🔴 Lines 0.57% 267/46820

Test suite run success

19 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from cde5384

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

💸 Perf - Early-return ButtonRow before its layout-measuring hooks

1 participant