askill
react-conventions

react-conventionsSafety 100Repository

React 18+ conventions with React Compiler guidance (no manual memoization, functional components, hooks patterns). Use when authoring components, hooks, or reviewing React code for styling and performance issues.

2 stars
1.2k downloads
Updated 2/22/2026

Package Files

Loading files...
SKILL.md

React Conventions Skill

What This Skill Does

Captures React best practices for this project with emphasis on React Compiler compatibility:

  • Compiler-ready code - No manual memoization (useMemo, useCallback, memo)
  • Functional components - Plain functions, hooks-based patterns only
  • Styling patterns - Tailwind CSS integration and best practices
  • Component organization - One main export per file, colocated tests
  • Hook patterns - Proper dependency arrays, no stale closures
  • Type safety - Strong prop typing with TypeScript

When to Use

  • Authoring new React components, hooks, or pages
  • Reviewing PRs for React patterns and performance
  • Implementing component-specific styling or state management
  • Migrating code to React Compiler (removing manual optimizations)
  • Creating custom hooks or composable logic

Key Rules

1. React Compiler Ready

Never use manual memoization - React Compiler handles optimization automatically:

// ❌ BAD: Unnecessary memoization
const MyComponent = memo(() => {
  return <div>Content</div>;
});

const handleClick = useCallback(() => {
  console.log("clicked");
}, []);

const computedValue = useMemo(() => expensiveComputation(), [deps]);

✅ GOOD: Plain functions - Compiler optimizes automatically:

function MyComponent(): JSX.Element {
  // Plain function - no memo needed
  return <div>Content</div>;
}

function handleClick(): void {
  // Plain function - no useCallback needed
  console.log("clicked");
}

const computedValue = expensiveComputation(); // No useMemo needed

When to break this rule: Only if there's documented evidence of performance regression. Then add a comment explaining why:

// NOTE: Profiling showed unnecessary re-renders (see GitHub issue #123).
// Memoization reduces re-renders from 5x to 1x in this scenario.
const MemoizedComponent = memo(ExpensiveComponent);

2. Functional Components Only

All components are functional components with hooks:

// ❌ BAD: Class components
class UserProfile extends React.Component {
  render() {
    return <div>{this.props.name}</div>;
  }
}

// ✅ GOOD: Functional component
function UserProfile(props: UserProfileProps): JSX.Element {
  return <div>{props.name}</div>;
}

3. Hook Patterns

Proper dependency arrays:

// ❌ BAD: Missing or incorrect dependencies
useEffect(() => {
  fetchUser(userId); // userId not in deps - stale closure!
}, []);

// ✅ GOOD: Complete dependency array
useEffect(() => {
  fetchUser(userId);
}, [userId]); // userId included

No hook rules violations:

// ❌ BAD: Hook inside conditional
if (user.isActive) {
  useState("initial"); // NEVER - breaks hook rules
}

// ✅ GOOD: Hooks at top level
const [state, setState] = useState("initial");

4. Component Organization

One main component per file:

// ✅ GOOD: SongCard.tsx - single responsibility
export function SongCard(props: SongCardProps): JSX.Element {
  return <div>{/* ... */}</div>;
}

// ✅ GOOD: Colocated test
// SongCard.test.tsx in same directory

Colocated tests:

react/src/components/
  SongCard.tsx
  SongCard.test.tsx      ← Same directory
  UserMenu.tsx
  UserMenu.test.tsx

5. Prop Typing

Always type component props:

// ❌ BAD: No prop types
function Button(props) {
  return <button>{props.label}</button>;
}

// ✅ GOOD: Explicit prop type
type ButtonProps = {
  label: string;
  onClick?: () => void;
  disabled?: boolean;
};

function Button({ label, onClick, disabled }: ButtonProps): JSX.Element {
  return (
    <button onClick={onClick} disabled={disabled}>
      {label}
    </button>
  );
}

6. State Management

Use Zustand for shared state:

// ✅ GOOD: Zustand store with selector
export const useAppStore = create((set) => ({
  user: null,
  setUser: (user) => set({ user }),
}));

// In component - use selector to avoid unnecessary re-renders
function MyComponent() {
  const user = useAppStore((state) => state.user);
  return <div>{user?.name}</div>;
}

Local state with useState for component-local data:

// ✅ GOOD: Local state for form
function LoginForm(): JSX.Element {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleSubmit = async () => {
    // Use email and password
  };

See Zustand patterns guide for detailed store patterns, async operations, middleware, and testing.

return ...; }


### 7. Styling with Tailwind

**Use Tailwind utility classes:**

```typescript
// ✅ GOOD: Tailwind classes
function Card(): JSX.Element {
  return (
    <div className="rounded-lg border border-gray-200 bg-white p-4 shadow">
      <h2 className="text-lg font-semibold">Title</h2>
    </div>
  );
}

// ✅ GOOD: Dynamic classes with clsx if needed
import { clsx } from "clsx";

function Badge({ variant }: { variant: "primary" | "secondary" }): JSX.Element {
  return (
    <span
      className={clsx(
        "px-3 py-1 rounded-full text-sm font-medium",
        variant === "primary"
          ? "bg-blue-500 text-white"
          : "bg-gray-100 text-gray-700",
      )}
    >
      Badge
    </span>
  );
}

Common Pitfalls

❌ Removing manual optimizations when migrating to React Compiler

// BAD: Keep useCallback when migrating
const handleClick = useCallback(() => {
  console.log("clicked");
}, []);

// GOOD: Remove manual memoization
function handleClick() {
  console.log("clicked");
}

❌ Stale closures in event handlers

// BAD: userId is captured at component creation
function UserCard({ userId }: { userId: string }) {
  const handleDelete = () => {
    deleteUser(userId); // Stale userId!
  };

  return <button onClick={handleDelete}>Delete</button>;
}

// GOOD: userId is passed when event fires
function UserCard({ userId }: { userId: string }): JSX.Element {
  return (
    <button onClick={() => deleteUser(userId)}>
      Delete
    </button>
  );
}

❌ Missing ReactElement import (not needed!)

// BAD: Unnecessary import
import type { ReactElement } from "react";

function MyComponent(): ReactElement {
  return <div>content</div>;
}

// GOOD: ReactElement is ambient (globally available)
function MyComponent() {
  return <div>content</div>;
}

Deep Reference

For detailed technical reference on React Compiler behavior, hook patterns, state management with Zustand, Tailwind styling, and component composition patterns, see the reference guide.

Validation Commands

# Type check
npx tsc -b .

# Lint (includes React/Compiler rules)
npm run lint

# Unit tests
npm run test:unit

# Check for manual memoization (use sparingly)
grep -r "useMemo\|useCallback\|memo(" react/src --include="*.tsx"

References

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

93/100Analyzed 3 weeks ago

Comprehensive React 18+ conventions skill with excellent coverage of React Compiler guidance, functional components, hooks patterns, Tailwind styling, and Zustand state management. Features 7 detailed rules with clear good/bad code examples, dedicated 'When to Use' section, validation commands, and external references. Minor reductions: project-specific path references and generic tags moderately limit portability. Highly actionable and well-structured - strong bonus for dedicated skills folder location and comprehensive technical content.

100
95
85
92
90

Metadata

Licenseunknown
Version-
Updated2/22/2026
Publisherbkinsey808

Tags

githublintingtesting