Skip to content

Comments

perf(useRefObjectAsForwardedRef): add dependency array to useImperativeHandle#7553

Merged
hectahertz merged 8 commits intomainfrom
hectahertz/perf-useRefObjectAsForwardedRef-add-deps
Feb 20, 2026
Merged

perf(useRefObjectAsForwardedRef): add dependency array to useImperativeHandle#7553
hectahertz merged 8 commits intomainfrom
hectahertz/perf-useRefObjectAsForwardedRef-add-deps

Conversation

@hectahertz
Copy link
Contributor

@hectahertz hectahertz commented Feb 15, 2026

Closes #

useRefObjectAsForwardedRef calls useImperativeHandle without a dependency array, causing the factory function to re-run on every render. Since the ref object (from useRef) is stable, adding [refObject] as the dependency means the factory runs once after mount and is skipped on all subsequent re-renders.

13 components use this hook (~90-340 instances on a typical GitHub page):

Component Typical instances per page
Button 20-50+
Link 50-200+
Heading 5-15
ActionList.Heading 2-10
Overlay 1-3
Dialog 0-2
ActionBar 1-5
AutocompleteInput 0-2
AutocompleteOverlay 0-1
PageLayout 1
TextInputWithTokens 0-2
Text 10-50
deprecated Dialog 0-1

With the [refObject] dependency array, ~100-300 unnecessary factory calls per re-render cycle drop to 0 after mount.

Measurements (500 Buttons, changing count prop)

Branch Avg re-render (ms)
main (no deps) 70.77
This PR (with deps) 69.65

The ~1ms improvement per 500 components is expected given the factory is trivial (() => refObject.current). The real benefit is eliminating unnecessary work in React's commit phase across all 13 consuming components on every re-render.

Changelog

New

N/A

Changed

  • useImperativeHandle now has a [refObject] dependency array, preventing the factory from re-running every render

Removed

N/A

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

Testing & Reviewing

  1. Verify ref forwarding works on any component using this hook (Button, Dialog, Overlay, Link, Heading, etc.)
  2. ref.current should point to the correct DOM element after mount and after re-renders

Merge checklist

  • Added/updated tests
  • Added/updated documentation
  • Added/updated previews (Storybook)
  • Changes are SSR compatible
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge
  • (GitHub staff only) Integration tests pass at github/github

@changeset-bot
Copy link

changeset-bot bot commented Feb 15, 2026

🦋 Changeset detected

Latest commit: 5026569

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Feb 15, 2026
@github-actions
Copy link
Contributor

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Or, apply the integration-tests: skipped manually label to skip these checks.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a performance optimization to the useRefObjectAsForwardedRef hook by adding a dependency array to the useImperativeHandle call. The hook is used by 13 components throughout the codebase to synchronize a local ref object with a forwarded ref, enabling both local and external access to DOM elements.

Changes:

  • Added [refObject] dependency array to useImperativeHandle in useRefObjectAsForwardedRef
  • Added explanatory comments documenting why the dependency array is needed
  • Created changeset for patch release

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
packages/react/src/hooks/useRefObjectAsForwardedRef.ts Added dependency array [refObject] to useImperativeHandle to prevent factory function from re-running on every render, since ref objects from useRef are stable
.changeset/use-ref-object-add-deps.md Added changeset documenting the performance improvement as a patch release

@primer-integration
Copy link

👋 Hi from github/github-ui! Your integration PR is ready: https://github.com/github/github-ui/pull/14135

@primer-integration
Copy link

Integration test results from github/github-ui:

Passed  CI   Passed
Waiting  VRT   Waiting
Passed  Projects   Passed

@hectahertz hectahertz added this pull request to the merge queue Feb 20, 2026
Merged via the queue into main with commit 6225ba2 Feb 20, 2026
49 of 50 checks passed
@hectahertz hectahertz deleted the hectahertz/perf-useRefObjectAsForwardedRef-add-deps branch February 20, 2026 14:32
@primer primer bot mentioned this pull request Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants