Skip to content

fix: remove legacy browser API fallbacks#1663

Merged
xobotyi merged 3 commits into
react-hookz:masterfrom
lennondotw:fix/compat
Jul 22, 2026
Merged

fix: remove legacy browser API fallbacks#1663
xobotyi merged 3 commits into
react-hookz:masterfrom
lennondotw:fix/compat

Conversation

@lennondotw

@lennondotw lennondotw commented Oct 23, 2025

Copy link
Copy Markdown
Contributor

Summary

Removes the remaining code paths that pretend standard browser APIs may be missing. createQueryEntry in useMediaQuery subscribes with addEventListener unconditionally, so the deprecated removeListener fallback in queryUnsubscribe was asymmetric dead code — and the same "API might not exist" defensiveness lingered in useNetworkState and the shared on/off helpers.

Changes

  • useMediaQuery: queryUnsubscribe uses removeEventListener directly, matching createQueryEntry (Safari < 14 fallback removed)
  • useNetworkState: dropped mozConnection/webkitConnection — every browser shipping the Network Information API exposes unprefixed navigator.connection; Firefox and Safari don't ship it at all
  • util/misc.ts: on/off no longer optional-chain addEventListener/removeEventListener — the EventTarget constraint guarantees the methods exist; a non-EventTarget target now throws instead of silently doing nothing
  • usePermission tests: mocks gained the listener methods a real PermissionStatus always has (the silent no-op in on/off was masking the incomplete mocks)

Testing

  • yarn lint
  • yarn test — full suite, 527 tests across 117 files
  • yarn build

@lennondotw lennondotw changed the title fix(useMediaQuery): restore addEventListener compatibility check for symmetry Fix compatibility issue for useMediaQuery Oct 23, 2025
@xobotyi xobotyi self-assigned this Jan 11, 2026
@xobotyi
xobotyi requested a review from Copilot January 11, 2026 16:44

Copilot AI left a comment

Copy link
Copy Markdown

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 fixes a compatibility issue in the useMediaQuery hook where event listener subscription and unsubscription were handled asymmetrically, causing errors in Safari versions < 14 that only support the deprecated addListener/removeListener methods.

Changes:

  • Restored the addEventListener/addListener compatibility check in the createQueryEntry function to match the existing compatibility logic in queryUnsubscribe
  • Ensures symmetric handling of event listeners for both subscription and unsubscription operations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/useMediaQuery/index.ts Outdated
@lennondotw lennondotw changed the title Fix compatibility issue for useMediaQuery fix(useMediaQuery): remove asymmetric addListener/removeListener fallback in unsubscribe Apr 3, 2026
@lennondotw

Copy link
Copy Markdown
Contributor Author

Rebased on latest master and updated the fix — the original PR was adding back the addListener fallback, but since #1661 intentionally removed it from createQueryEntry, the right fix is to also remove the asymmetric removeListener fallback from queryUnsubscribe. Now both sides consistently use the standard addEventListener/removeEventListener API.

@xobotyi would you mind taking a look? It's a small cleanup — just removing 4 lines.

@lennondotw

Copy link
Copy Markdown
Contributor Author

@xobotyi I rebased this PR onto the latest master and re-checked whether it is still relevant.

Current master still has the asymmetric listener cleanup in useMediaQuery: createQueryEntry subscribes with mql.addEventListener(...) unconditionally, while queryUnsubscribe still branches to the deprecated removeListener fallback. This PR now only removes that stale fallback, so subscribe/unsubscribe consistently use addEventListener/removeEventListener.

Validation on the rebased branch:

  • yarn install --immutable
  • yarn vitest --run src/useMediaQuery/index.dom.test.ts src/useMediaQuery/index.ssr.test.ts -> 12 tests passed
  • yarn lint src/useMediaQuery/index.ts src/useMediaQuery/index.dom.test.ts src/useMediaQuery/index.ssr.test.ts
  • yarn build

The previous Copilot review thread is outdated now, since this PR intentionally removes the legacy fallback rather than preserving it.

@xobotyi xobotyi changed the title fix(useMediaQuery): remove asymmetric addListener/removeListener fallback in unsubscribe fix: remove legacy browser API fallbacks Jul 22, 2026
@xobotyi

xobotyi commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Rebased onto current master and broadened the scope: the same "standard API might be missing" defensiveness existed in useNetworkState (vendor-prefixed connection fallbacks) and the shared on/off helpers (optional-chained listener methods), so those are cleaned up here as well. Title and description updated accordingly.

lennondotw and others added 3 commits July 22, 2026 12:02
…back in unsubscribe

createQueryEntry uses addEventListener unconditionally, but
queryUnsubscribe still had a removeEventListener/removeListener
fallback. This asymmetry is unnecessary since all supported
browsers now have addEventListener on MediaQueryList.
mozConnection and webkitConnection existed only on old Firefox for
Android and pre-61 Chromium; every browser exposing the Network
Information API today ships unprefixed navigator.connection. Firefox
and Safari do not ship the API at all.
on/off called addEventListener/removeEventListener via optional
chaining, turning a call on a non-EventTarget into a silent no-op
that hides subscription bugs. The type constraint already guarantees
the methods exist; invalid runtime targets now throw.

usePermission test mocks gain the listener methods a real
PermissionStatus always has.
@xobotyi

xobotyi commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution.
I think i will start a series of reworks focused on non-standard behaviors (which usually is safari related🤦), supporting non-standard would be a task for bundler shimming layer.

Will be released somewhat today, along with deps upgrade

@xobotyi
xobotyi merged commit fb8dbab into react-hookz:master Jul 22, 2026
6 checks passed
@xobotyi

xobotyi commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 25.2.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Development

Successfully merging this pull request may close these issues.

3 participants