fix: resolve new ESLint rules from eslint-plugin-react-hooks update
- Use useId() instead of Math.random() for stable ID generation in Checkbox and Switch - Use deterministic rotation/delay calculations instead of Math.random() in CategoryGrid and ProblemSection - Add eslint-disable comments for intentional setState in useEffect patterns: - Hydration safety (setMounted) - Initial localStorage sync - Route-based UI sync - Controlled component sync - Browser API initial sync (scroll position, media queries) - Add eslint-disable for ref merging pattern in AnimatedCounter and StatCard 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5e0651b987
commit
52c7d8d844
11 changed files with 35 additions and 20 deletions
|
|
@ -82,8 +82,9 @@ export const AnimatedCounter = forwardRef<HTMLSpanElement, AnimatedCounterProps>
|
|||
return (
|
||||
<span
|
||||
ref={(node) => {
|
||||
// Assign to both refs
|
||||
// Assign to both refs - this is a standard ref callback pattern for merging refs
|
||||
if (scrollRef) {
|
||||
// eslint-disable-next-line react-hooks/immutability
|
||||
(scrollRef as React.MutableRefObject<HTMLSpanElement | null>).current = node;
|
||||
}
|
||||
if (typeof ref === 'function') {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { cn } from '@tpmjs/utils/cn';
|
||||
import { forwardRef, useEffect, useRef } from 'react';
|
||||
import { forwardRef, useEffect, useId, useRef } from 'react';
|
||||
import type { CheckboxProps } from './types';
|
||||
import { checkboxLabelVariants, checkboxUIVariants, checkboxVariants } from './variants';
|
||||
|
||||
|
|
@ -66,7 +66,8 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|||
}, [indeterminate]);
|
||||
|
||||
// Generate unique ID if not provided
|
||||
const checkboxId = id || `checkbox-${Math.random().toString(36).substring(2, 9)}`;
|
||||
const generatedId = useId();
|
||||
const checkboxId = id || `checkbox-${generatedId}`;
|
||||
|
||||
const checkboxInput = (
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -70,8 +70,9 @@ export const StatCard = forwardRef<HTMLDivElement, StatCardProps>(
|
|||
return (
|
||||
<div
|
||||
ref={(node) => {
|
||||
// Assign to both refs
|
||||
// Assign to both refs - this is a standard ref callback pattern for merging refs
|
||||
if (scrollRef) {
|
||||
// eslint-disable-next-line react-hooks/immutability
|
||||
(scrollRef as React.MutableRefObject<HTMLDivElement | null>).current = node;
|
||||
}
|
||||
if (typeof ref === 'function') {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { cn } from '@tpmjs/utils/cn';
|
||||
import { forwardRef } from 'react';
|
||||
import { forwardRef, useId } from 'react';
|
||||
import { useControlled } from '../system/useControlled';
|
||||
import type { SwitchProps } from './types';
|
||||
import {
|
||||
|
|
@ -85,7 +85,8 @@ export const Switch = forwardRef<HTMLButtonElement, SwitchProps>(
|
|||
};
|
||||
|
||||
// Generate unique ID if not provided
|
||||
const switchId = id || `switch-${Math.random().toString(36).substring(2, 9)}`;
|
||||
const generatedId = useId();
|
||||
const switchId = id || `switch-${generatedId}`;
|
||||
|
||||
// Determine data-state for styling
|
||||
const dataState = checked ? 'checked' : 'unchecked';
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ export function useParallax(options: UseParallaxOptions = {}): React.CSSProperti
|
|||
}
|
||||
};
|
||||
|
||||
// Initial scroll position
|
||||
// Initial scroll position - intentional initial sync from browser API
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setScrollY(window.scrollY);
|
||||
|
||||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ export function useReducedMotion(): boolean {
|
|||
// Create media query
|
||||
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||
|
||||
// Set initial value
|
||||
// Set initial value - intentional initial sync from browser API
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setPrefersReducedMotion(mediaQuery.matches);
|
||||
|
||||
// Update on change
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue