Skip to content

πŸ› Bug: matchMedia change listener in FaviconHead is not cleaned up on unmountΒ #2263

Description

@severe77

Describe the bug

In components/Layout.tsx, inside the FaviconHead component (around lines 500–510),
a matchMedia('(prefers-color-scheme: dark)') change listener is added inside a useEffect
without a cleanup function.

The listener uses an anonymous handler:

matcher.addEventListener('change', () => onUpdate(matcher));

Since the handler is anonymous and no removeEventListener is called,
the listener cannot be removed if the component unmounts.

This does not follow recommended React effect practices and may lead to
event listener accumulation in certain scenarios.

Steps To Reproduce

  1. Render the Layout component (for example, by navigating to any page).
  2. Unmount and remount the component (e.g., during layout changes or future refactors).
  3. Toggle the system color scheme between light and dark.
  4. Repeat the remount process multiple times.

Because the matchMedia listener is not cleaned up, multiple listeners could accumulate across mounts over time.

Expected Behavior

The matchMedia 'change' listener should use a named handler function
and be removed in the useEffect cleanup function when the component
unmounts.

This ensures proper React lifecycle handling and avoids potential
event listener accumulation across mounts.

Screenshots

Image See attached screenshot highlighting lines ~502–508 in components/Layout.tsx where addEventListener is called without a corresponding cleanup function.

Device Information [optional]

- OS: Any
- Browser: Any
- version: N/A

Are you working on this issue?

Yes

Do you think this work might require an [Architectural Decision Record (ADR)]? (significant or noteworthy)

No

Metadata

Metadata

Assignees

Labels

Status: TriageThis is the initial status for an issue that requires triage.πŸ› BugIndicates that the issue is a bug or defect.

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions