fix: optimize prefers-reduced-motion listener initialization#3453
fix: optimize prefers-reduced-motion listener initialization#3453mattgperry merged 2 commits intomainfrom
Conversation
Only initialize the matchMedia listener for prefers-reduced-motion when the reducedMotionConfig is not explicitly set to "never" or "always". This avoids adding unnecessary event listeners when the motion preference is statically configured. Related to: #3304, #2444 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review: PR #3453SummaryThis PR optimizes the initialization of the ✅ Positive Aspects1. Performance & Memory Optimization
2. Code Quality
3. Correctness
🔍 Observations & Suggestions1. Test Coverage Gap
Recommendation: Consider adding tests like: describe("reduced motion listener initialization", () => {
it("should not initialize listener when reducedMotionConfig is 'never'", () => {
// Mock initPrefersReducedMotion and verify it's not called
})
it("should not initialize listener when reducedMotionConfig is 'always'", () => {
// Mock initPrefersReducedMotion and verify it's not called
})
it("should initialize listener when reducedMotionConfig is 'user'", () => {
// Verify listener is created
})
})2. Default Case Handling // Current (implicit):
} else {
// handles "user" and undefined
// Alternative (explicit):
} else if (this.reducedMotionConfig === "user" || !this.reducedMotionConfig) {Though the current approach is fine if the default behavior is intentional. 3. Listener Cleanup Consideration motionMediaQuery.addEventListener("change", setReducedMotionPreferences)While this PR doesn't introduce this issue (it was pre-existing), and the listener is only created once per application lifecycle via the Potential future enhancement: Track the listener reference and provide a cleanup function, or use a reference counter to remove the listener when the last VisualElement unmounts. 4. Minor: Comment Clarity /**
* Determine reduced motion preference. Only initialize the matchMedia
* listener if we actually need the dynamic value (i.e., when config
* is neither "never" nor "always", meaning it's "user" or undefined).
*/🎯 Final AssessmentApproval: ✅ LGTM with minor suggestions This is a solid optimization that addresses a real performance/memory concern with minimal risk. The logic is sound, the implementation is clean, and it maintains backward compatibility. Key Strengths:
Minor Improvement Opportunities:
Great work addressing this issue! 🚀 🤖 Review generated with Claude Code |
Add tests to verify:
- Listener is NOT initialized when reducedMotionConfig is 'never'
- Listener is NOT initialized when reducedMotionConfig is 'always'
- Listener IS initialized when reducedMotionConfig is 'user'
- Default config ('never') does not initialize listener
- Listener is only initialized once across multiple components
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code Review - PR #3453SummaryThis PR optimizes the ✅ Strengths
|
Summary
matchMedialistener forprefers-reduced-motionwhenreducedMotionConfigis not explicitly set to"never"or"always"Context
This addresses part of the memory leak issues discussed in:
When
reducedMotionConfigis set to"never"or"always", the dynamicprefersReducedMotion.currentvalue is never read, so there's no need to initialize thematchMedialistener.Closes #3304
Test plan
yarn build)yarn test)🤖 Generated with Claude Code