Skip to content

usePaneWidth triggers unnecessary React re-renders on every window resize #7801

@talum

Description

@talum

Description

Problem

👋🏼 Hello, while investigating a report of performance lag on https://github.com/github/pull-requests/issues/24571, I did a bit of profiling with Copilot.

I've made some changes on our end, but I would love it if y'all would investigate the below findings.

When SplitPageLayout has a resizable pane (resizable={true}), the usePaneWidth hook registers a window.addEventListener("resize", handleResize) listener that calls syncAll() on every resize event (~60/sec during a drag).

syncAll() unconditionally calls:

startTransition(() => {
  setMaxPaneWidth(actualMax);
  if (wasClamped) {
    setCurrentWidthState(actualMax);
  }
});

Even when the computed actualMax hasn't changed from the previous value, setMaxPaneWidth(actualMax) still schedules a React concurrent render because React doesn't bail out of startTransition state updates that set the same value (unlike normal setState).

Impact

On a page with multiple components consuming SplitPageLayout context (e.g. GitHub PR conversation tab), this produces 11 React scheduler calls totaling ~108ms in a single animation frame during resize — with 4× CPU throttle, this pushes individual frames well beyond 100ms and creates visible jank.

Trace evidence

  • Chrome Performance trace on a GitHub PR conversation page (4× CPU throttle)
  • The actualMax value doesn't change between most resize ticks (only changes when crossing the DEFAULT_PANE_MAX_WIDTH_DIFF_BREAKPOINT)

Suggested fix

Add a guard before the state update:

const syncAll = () => {
  // ... existing logic ...
  const actualMax = getMaxPaneWidthRef.current();
  paneRef.current?.style.setProperty("--pane-max-width", `${actualMax}px`);

  // Only trigger React re-render if values actually changed
  const maxChanged = actualMax !== maxPaneWidthRef.current;
  const wasClamped = currentWidthRef.current > actualMax;

  if (maxChanged || wasClamped) {
    startTransition(() => {
      setMaxPaneWidth(actualMax);
      if (wasClamped) {
        setCurrentWidthState(actualMax);
      }
    });
  }
};

This would skip the startTransition entirely when the computed max hasn't changed — which is the common case during horizontal resize that doesn't cross the breakpoint.

Additional context

  • The inline style updates (--pane-max-width, --pane-width) and ARIA updates are fine — they don't trigger React renders
  • Consumers can't work around this without disabling resizable entirely

Steps to reproduce

  1. Go to a Conversation page on a PR
  2. Throttle CPU
  3. Resize the window
  4. Observe lag

Version

v38.21.0

Browser

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions