react-doctor/no-permanent-will-change
Add will-change on animation start (`onMouseEnter`) and remove on end (`onAnimationEnd`). Permanent promotion wastes GPU memory and can degrade performance
- Category: Performance
- Severity: warn
- Source:
oxlint-plugin-react-doctor - Framework: global
- Enabled when: always
Validation prompt
Use this to decide whether a fired diagnostic is real or a false positive.
Confirm a JSX style attribute with an object expression containing a willChange key. The rule flags ANY static willChange value regardless of the actual property listed — the issue is keeping it set permanently rather than scoping it to active animation.
Fix prompt
Use this once validation confirms the diagnostic is real.
Toggle will-change imperatively: set it on onMouseEnter or animation start, then clear it on onMouseLeave / onAnimationEnd / onTransitionEnd (element.style.willChange = ''). For pure CSS hovers, scope it inside the :hover selector so the hint only exists while hovered. See https://developer.mozilla.org/en-US/docs/Web/CSS/will-change#using_will-change_responsibly
Related rules
More Performance rules from the rules reference:
react-doctor/no-scale-from-zero: Use `initial={{ scale: 0.95, opacity: 0 }}` — elements should deflate like a balloon, not vanish into a pointreact-doctor/no-transition-all: List specific properties: `transition: "opacity 200ms, transform 200ms"` — or in Tailwind use `transition-colors`, `transition-opacity`, or `transition-transform`react-doctor/no-unstable-nested-components: Hoist nested components to module scope or memoize them — never define one inside another.react-doctor/no-usememo-simple-expression: Remove useMemo — property access, math, and ternaries are already cheap without memoizationreact-doctor/prefer-stable-empty-fallback: Hoist a module-level const EMPTY = [] (or {}) and use it as the || / ?? fallback so the memoised child sees a stable reference