Loading...
Loading...
Provides comprehensive code review capability for React applications, validates component architecture, hooks usage, React 19 patterns, state management, performance optimization, accessibility compliance, and TypeScript integration. Use when reviewing React code changes, before merging pull requests, after implementing new features, or for component architecture validation. Triggers on "review React code", "React code review", "check my React components".
npx skill4agent add giuseppe-trisciuoglio/developer-kit react-code-reviewreact-software-architect-reviewglob.tsx.jsxgrepuseEffectuseMemouseCallbackuseEffectuseEffectuseStateReact.memouseCallbackuseMemoany// ❌ Bad: Missing dependency causes stale closure
function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, []); // Missing userId in dependency array
return <div>{user?.name}</div>;
}
// ✅ Good: Proper dependencies with cleanup
function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
let cancelled = false;
fetchUser(userId).then((data) => {
if (!cancelled) setUser(data);
});
return () => { cancelled = true; };
}, [userId]);
return <div>{user?.name}</div>;
}
// ✅ Better: Use TanStack Query for server state
function UserProfile({ userId }: { userId: string }) {
const { data: user, isLoading } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
});
if (isLoading) return <Skeleton />;
return <div>{user?.name}</div>;
}// ❌ Bad: Monolithic component mixing data fetching, filtering, and rendering
function Dashboard() {
const [users, setUsers] = useState([]);
const [filter, setFilter] = useState('');
useEffect(() => { /* fetch + filter + sort all in one */ }, [filter]);
return <div>{/* 200+ lines of mixed concerns */}</div>;
}
// ✅ Good: Composed from focused components with custom hooks
function Dashboard() {
return (
<div>
<UserFilters />
<Suspense fallback={<TableSkeleton />}>
<UserTable />
</Suspense>
<UserPagination />
</div>
);
}// ❌ Bad: Inaccessible interactive elements
function Menu({ items }: { items: MenuItem[] }) {
const [open, setOpen] = useState(false);
return (
<div>
<div onClick={() => setOpen(!open)}>Menu</div>
{open && (
<div>
{items.map(item => (
<div key={item.id} onClick={() => navigate(item.path)}>
{item.label}
</div>
))}
</div>
)}
</div>
);
}
// ✅ Good: Accessible with proper semantics and keyboard support
function Menu({ items }: { items: MenuItem[] }) {
const [open, setOpen] = useState(false);
return (
<nav aria-label="Main navigation">
<button
onClick={() => setOpen(!open)}
aria-expanded={open}
aria-controls="menu-list"
>
Menu
</button>
{open && (
<ul id="menu-list" role="menu">
{items.map(item => (
<li key={item.id} role="menuitem">
<a href={item.path}>{item.label}</a>
</li>
))}
</ul>
)}
</nav>
);
}// ❌ Bad: Unstable callback recreated every render causes child re-renders
{filtered.map(product => (
<ProductCard
key={product.id}
product={product}
onSelect={() => console.log(product.id)} // New function each render
/>
))}
// ✅ Good: Stable callback + memoized child
const handleSelect = useCallback((id: string) => {
console.log(id);
}, []);
const filtered = useMemo(
() => products.filter(p => p.name.toLowerCase().includes(search.toLowerCase())),
[products, search]
);
{filtered.map(product => (
<ProductCard key={product.id} product={product} onSelect={handleSelect} />
))}
const ProductCard = memo(function ProductCard({ product, onSelect }: Props) {
return <div onClick={() => onSelect(product.id)}>{product.name}</div>;
});// ❌ Bad: Loose typing and missing prop definitions
function Card({ data, onClick, children, ...rest }: any) {
return (
<div onClick={onClick} {...rest}>
<h2>{data.title}</h2>
{children}
</div>
);
}
// ✅ Good: Strict typing with proper interfaces
interface CardProps extends React.ComponentPropsWithoutRef<'article'> {
title: string;
description?: string;
variant?: 'default' | 'outlined' | 'elevated';
onAction?: (event: React.MouseEvent<HTMLButtonElement>) => void;
children: React.ReactNode;
}
function Card({
title,
description,
variant = 'default',
onAction,
children,
className,
...rest
}: CardProps) {
return (
<article className={cn('card', `card--${variant}`, className)} {...rest}>
<h2>{title}</h2>
{description && <p>{description}</p>}
{children}
{onAction && <button onClick={onAction}>Action</button>}
</article>
);
}React.memouseEffectuseStateuseEffectanyreferences/references/hooks-patterns.mdreferences/component-architecture.mdreferences/accessibility.md