Skip to content

fix(react): memoize Provider context value#1541

Open
R-Delfino95 wants to merge 1 commit into
videojs:mainfrom
mav2287:fix/1296-provider-value-attach-ref-churn
Open

fix(react): memoize Provider context value#1541
R-Delfino95 wants to merge 1 commit into
videojs:mainfrom
mav2287:fix/1296-provider-value-attach-ref-churn

Conversation

@R-Delfino95
Copy link
Copy Markdown
Collaborator

@R-Delfino95 R-Delfino95 commented May 13, 2026

Related to #1296

What changed

Diff: 2 files changed, 58 insertions(+), 7 deletions(-).

  • packages/react/src/player/create-player.tsx — Provider context value wrapped in useMemo keyed on [store, media, container, popupGroup]. setMedia and setContainer are omitted (identity-stable useState setters). popupGroup (added on main since the original PR was opened) is included in both the value and the dep array.

  • packages/react/src/player/tests/create-player.test.tsx — one regression test added: mounts a usePlayerContext() consumer, forces parent re-renders three times, asserts context value identity is preserved (toBe).

Test results in packages/react:

Step Result
Baseline (untouched main) 17 files, 237 passing
With fix applied 17 files, 238 passing (+1 new)
Source reverted, new test kept 1 new test fails (fail-before/pass-after contract)
Source re-applied 238/238 passing
pnpm typecheck (root) Clean
pnpm lint on the 2 changed files Clean

The attachMediaElement WeakMap fix has been fully discarded. Worth noting that #1376 has since landed on main, which introduced useAttachMedia (a useCallback-based hook keyed on [media]), so the ref-identity stability that fix #2 was guarding against is now handled at the hook level — fix #2 isn't just unwanted, it's obsolete against current main.


Note

Low Risk
Low risk: scoped to React context value memoization and adds a regression test; behavior should be unchanged except fewer unnecessary re-renders and attach/detach churn.

Overview
Fixes createPlayer().Provider to memoize the PlayerContext value via useMemo, so consumers don’t re-render (and trigger media detach/reattach) on unrelated parent renders (regression #1296).

Adds a test asserting the context value identity remains stable across repeated parent re-renders.

Reviewed by Cursor Bugbot for commit 9e29157. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2026

Someone is attempting to deploy a commit to the Mux Team on Vercel.

A member of the Team first needs to authorize it.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 13, 2026

👷 Deploy request for vjs10-site pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 9e29157

@R-Delfino95
Copy link
Copy Markdown
Collaborator Author

Hi @mav2287! I created the PR with your changes, as external PRs are currently restricted.
Regarding the fixes, only the useMemo adjustment (fix # 1) is necessary; the rest can be discarded.

Would you mind: 1. Updating the branch with upstream main, 2. Applying only that change and discarding the rest, 3. Updating the PR description?

Let me know if that works! Otherwise, I can pick up your contribution from where you left off.
Best!

The `Provider` returned by `createPlayer()` was building a fresh context
value object on every render. Every `useContext(PlayerContext)` consumer
therefore re-rendered on any parent re-render — even when none of the
value's members changed. Combined with callback-ref usage in media
components (`HlsVideo`, `DashVideo`, etc.), this caused the underlying
media to detach and re-attach on every parent state change. The most
visible symptom: `onEnded` fires, parent state updates, the video
rewinds to t=0 and plays again.

Wrap the value object in `useMemo` keyed on `[store, media, container,
popupGroup]`. `setMedia` and `setContainer` are `useState` setters and
are identity-stable; `store` and `popupGroup` are also initialized once
via `useState(() => ...)` and never change for the lifetime of the
Provider, but they're listed in the dep array to satisfy Biome's
`useExhaustiveDependencies`.

Adds a regression test that asserts context value identity is preserved
across forced parent re-renders.

Signed-off-by: James <james@BlainWebDesign.com>
@mav2287 mav2287 force-pushed the fix/1296-provider-value-attach-ref-churn branch from 22df048 to 9e29157 Compare May 13, 2026 22:54
@mav2287
Copy link
Copy Markdown

mav2287 commented May 13, 2026

@R-Delfino95 done — branch rebased and reduced to just the useMemo change, per your request. Force-pushed to mav2287:fix/1296-provider-value-attach-ref-churn. Summary of what's now on the branch:

Diff: 2 files changed, 58 insertions(+), 7 deletions(-).

  • packages/react/src/player/create-player.tsx — Provider context value wrapped in useMemo keyed on [store, media, container, popupGroup]. setMedia and setContainer are omitted (identity-stable useState setters). popupGroup (added on main since the original PR was opened) is included in both the value and the dep array.

  • packages/react/src/player/tests/create-player.test.tsx — one regression test added: mounts a usePlayerContext() consumer, forces parent re-renders three times, asserts context value identity is preserved (toBe).

Test results in packages/react:

Step Result
Baseline (untouched main) 17 files, 237 passing
With fix applied 17 files, 238 passing (+1 new)
Source reverted, new test kept 1 new test fails (fail-before/pass-after contract)
Source re-applied 238/238 passing
pnpm typecheck (root) Clean
pnpm lint on the 2 changed files Clean

The attachMediaElement WeakMap fix has been fully discarded. Worth noting that #1376 has since landed on main, which introduced useAttachMedia (a useCallback-based hook keyed on [media]), so the ref-identity stability that fix #2 was guarding against is now handled at the hook level — fix #2 isn't just unwanted, it's obsolete against current main.

Commit is DCO-signed.

I don't have permission to edit the PR title/body myself (only you can as the PR author). When you get a chance, would you mind updating them to reflect the single-change scope? Happy to draft a new description if helpful — let me know.

Thanks again for picking this up on our behalf!

@R-Delfino95 R-Delfino95 marked this pull request as ready for review May 14, 2026 14:39
@R-Delfino95 R-Delfino95 changed the title fix(react): memoize Provider context value and cache attachMediaElement refs fix(react): memoize Provider context value May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants