К основному содержанию
правило

react · sanjeed5 — правило для Cursor: стандарты React и TypeScript

Правило для Cursor задаёт команде единые стандарты React: чистые компоненты, правила хуков, структура по фичам. Пригодится, когда в проекте несколько разработчиков и ИИ-агент пишет код вразнобой.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/react.mdc
Открыть на GitHub

Что делает react

Файл .cursor/rules/react.mdc подключается к Cursor и срабатывает на файлы **/*.{jsx,tsx}. Внутри — свод правил, разбитый на разделы: принципы чистоты компонентов и Rules of Hooks, организация кода и именование, разделение на умные и презентационные компоненты, работа с состоянием, оптимизация производительности. К каждому пункту идёт пара примеров: как не надо и как надо.

Агент получает конкретные ориентиры. Хуки вызываются только на верхнем уровне, данные сортируются иммутабельно через useMemo, состояние поднимается вверх или уходит в Context API вместо протаскивания пропсов через три уровня. Для сложного глобального состояния правило советует начать с useState и useReducer, а библиотеки вроде Zustand или Redux Toolkit подключать позже.

Оптимизацию правило советует начинать после профилирования, а не заранее: React.memo и useCallback применяются точечно. Обратите внимание на зависимости в useCallback — пример с пустым массивом и устаревшим замыканием показывает, где чаще всего ломается код. Правило рассчитано на TypeScript и компоненты в .tsx.

Какие задачи решает

  • договориться о едином стиле React-кода в команде
  • объяснить агенту, когда нужен useMemo, а когда это преждевременная оптимизация
  • разложить проект по фичам вместо свалки компонентов
  • убрать протаскивание пропсов через несколько уровней
  • поймать устаревшее замыкание в useCallback

Примеры запросов агенту

  • Отрефактори ProductList: убери сортировку массива прямо в рендере
  • Разложи папку components по фичам, как описано в правиле react
  • Проверь зависимости в useCallback в этом файле

Как установить react

Вручную: положить файлы

.cursor/rules/react.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о react

Как установить react в Cursor?

Создайте файл .cursor/rules/react.mdc в корне проекта и вставьте в него содержимое правила.

Что делает правило react?

Задаёт Cursor стандарты написания React-приложений на TypeScript: чистые компоненты, правила хуков, структура по фичам, работа с состоянием и точечная оптимизация.

На какие файлы распространяется правило?

На всё, что попадает под **/*.{jsx,tsx} — компоненты и хуки в JSX и TSX.

Исходный текст

react.mdc · CC0-1.0
---
description: Definitive guidelines for writing idiomatic, maintainable, and performant React applications using modern best practices and TypeScript.
globs: **/*.{jsx,tsx}
---
# react Best Practices

This guide outlines the non-negotiable standards for building React applications within our team. Adherence ensures predictable behavior, simplifies debugging, and enables future optimizations.

## 1. Core React Principles: Purity & Rules of Hooks

Components and Hooks **must be pure**. They should always return the same output given the same inputs (props, state, context) and not cause side effects during rendering. Obey the [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks) without exception.

### ❌ BAD: Impure component / Side effect in render
```tsx
function ProductList({ products }) {
  // ❌ Modifies external data during render
  products.sort((a, b) => a.name.localeCompare(b.name));
  return (/* ... */);
}

function MyComponent() {
  // ❌ Hook called conditionally
  if (Math.random() > 0.5) {
    const [count, setCount] = useState(0);
  }
  return (/* ... */);
}
```

### ✅ GOOD: Pure component / Correct Hook usage
```tsx
import { useMemo, useState } from 'react';

function ProductList({ products }) {
  // ✅ Sort data immutably or memoize if expensive
  const sortedProducts = useMemo(() => 
    [...products].sort((a, b) => a.name.localeCompare(b.name)),
    [products]
  );
  return (/* ... */);
}

function MyComponent() {
  // ✅ Hooks always at the top level
  const [count, setCount] = useState(0); 
  // ... conditional logic after hooks
  return (/* ... */);
}
```

## 2. Code Organization & Naming

Organize code by **feature** using the `bulletproof-react` pattern. Use TypeScript (`.tsx`) for all components.

*   **One Component Per File**: Except for small, pure, stateless components closely related to a parent.
*   **Naming**:
    *   Components: `PascalCase` (e.g., `UserProfile.tsx`)
    *   Custom Hooks: `use` prefix + `PascalCase` (e.g., `useAuth.ts`)
    *   Functions/Variables: `camelCase`
    *   CSS Classes: `kebab-case` (via CSS Modules or utility classes)

### ✅ GOOD: Feature-based structure
```
src/
├── features/
│   ├── auth/
│   │   ├── components/
│   │   │   ├── LoginForm.tsx
│   │   │   └── AuthButton.tsx
│   │   ├── hooks/
│   │   │   └── useAuth.ts
│   │   └── api/auth.ts
│   └── products/
│       ├── components/
│       │   ├── ProductCard.tsx
│       │   └── ProductList.tsx
│       └── hooks/useProducts.ts
├── components/ui/  // Reusable, generic UI components
│   ├── Button.tsx
│   └── Modal.tsx
└── App.tsx
```

## 3. Component Design & Patterns

Prioritize **function components with Hooks**. Separate concerns into "smart" (data/logic) and "dumb" (presentational) components.

### ❌ BAD: Class components / Mixed concerns
```tsx
// ❌ Class component (avoid)
class UserProfile extends React.Component { /* ... */ }

// ❌ Component fetches data AND renders complex UI
function ProductPage() {
  const [products, setProducts] = useState([]);
  useEffect(() => { /* fetch products */ }, []);
  return (/* complex product list UI */);
}
```

### ✅ GOOD: Function components / Separation of concerns
```tsx
// ✅ Use function components with hooks
function UserProfile({ user }) { /* ... */ }

// ✅ Smart component (container) handles data fetching
function ProductListContainer() {
  const { products, isLoading } = useProducts(); // Custom hook for data
  if (isLoading) return <LoadingSpinner />;
  return <ProductList products={products} />; // Renders dumb component
}

// ✅ Dumb component (presentational) focuses on UI
function ProductList({ products }) {
  return (
    <ul>
      {products.map(product => <ProductCard key={product.id} product={product} />)}
    </ul>
  );
}
```

## 4. State Management

Start with **local state (`useState`, `useReducer`)**. Lift state up when necessary. Use **Context API** for global state that rarely changes. For complex global state, use dedicated libraries (e.g., Zustand, Jotai, Redux Toolkit). **Avoid prop drilling.**

### ❌ BAD: Prop drilling
```tsx
function Grandparent() {
  const [theme, setTheme] = useState('dark');
  return <Parent theme={theme} setTheme={setTheme} />;
}
function Parent({ theme, setTheme }) {
  return <Child theme={theme} setTheme={setTheme} />;
}
function Child({ theme, setTheme }) {
  return <Button onClick={() => setTheme('light')}>Toggle Theme</Button>;
}
```

### ✅ GOOD: Context API for global state
```tsx
import { createContext, useContext, useState, ReactNode } from 'react';

type Theme = 'light' | 'dark';
type ThemeContextType = { theme: Theme; toggleTheme: () => void };

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [theme, setTheme] = useState<Theme>('dark');
  const toggleTheme = () => setTheme(prev => (prev === 'dark' ? 'light' : 'dark'));
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

export const useTheme = () => {
  const context = useContext(ThemeContext);
  if (context === undefined) {
    throw new Error('useTheme must be used within a ThemeProvider');
  }
  return context;
};

// Usage:
function MyComponent() {
  const { theme, toggleTheme } = useTheme();
  return <button onClick={toggleTheme}>Current theme: {theme}</button>;
}
```

## 5. Performance & Optimization

Optimize only when profiling indicates a bottleneck. Use `React.memo`, `useCallback`, `useMemo` judiciously.

### ❌ BAD: Premature optimization / Incorrect memoization
```tsx
// ❌ Memoizing a component that re-renders frequently or has no expensive props
const MyButton = React.memo(({ onClick, children }) => <button onClick={onClick}>{children}</button>);

// ❌ Callback with missing dependency, causing stale closure
function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = useCallback(() => {
    console.log(count); // ❌ 'count' is stale if not in dependency array
  }, []); 
  return <Child onClick={handleClick} />;
}
```

### ✅ GOOD: Targeted optimization / Correct dependencies
```tsx
import React, { useCallback, useMemo, useState } from 'react';

// ✅ Memoize only if component is expensive AND props are stable
const ExpensiveList = React.memo(({ items }) => {
  console.log('Rendering ExpensiveList');
  return (/* ... render many items ... */);
});

function Parent() {
  const [count, setCount] = useState(0);
  // ✅ Callback with correct dependencies
  const handleClick = useCallback(() => {
    setCount(prev => prev + 1); // Use functional update to avoid 'count' in deps
  }, []); 

  // ✅ Memoize expensive calculations
  const computedValue = useMemo(() => {
    // ... heavy computation based on count ...
    return count * 2;
  }, [count]);

  return (
    <>
      <ExpensiveList items={[{ id: 1, name: 'Item 1' }]} /> {/* Example usage */}
      <Child onClick={handleClick} />
      <p>Count: {count}, Computed: {computedValue}</p>
    </>
  );
}
// Child component that receives the memoized callback
const Child = React.memo(({ onClick }: { onClick: () => void }) => {
  console.log('Rendering Child');
  return <button onClick={onClick}>Increment</button>;
});
```

## 6. Common Pitfalls

*   **Never mutate props or state directly.** Always create new objects/arrays.
*   **Never call component functions directly.** Use JSX.
*   **Ensure `useEffect` cleanup functions are always provided** for subscriptions or timers.
*   **Correct `useEffect` dependency arrays** are critical to avoid infinite loops or stale closures.

### ❌ BAD: Direct mutation / Calling component as function
```tsx
function MyComponent({ items }) {
  // ❌ Mutating props directly
  items.push('new item'); 

  const [data, setData] = useState({ value: 1 });
  // ❌ Mutating state directly
  data.value = 2; 
  setData(data);

  // ❌ Calling component as a function
  return MyOtherComponent(); 
}
```

### ✅ GOOD: Immutable updates / JSX usage
```tsx
function MyComponent({ items }) {
  const [data, setData] = useState({ value: 1 });

  // ✅ Create a new array for updates
  const updatedItems = [...items, 'new item']; 

  // ✅ Create a new object for state updates
  setData(prevData => ({ ...prevData, value: 2 }));

  // ✅ Use JSX for components
  return <MyOtherComponent />;
}
```

## 7. Accessibility (A11y) & Testing

Build for accessibility from the start. Test components as a user would.

*   **Semantic HTML**: Use native HTML elements (`<button>`, `<input>`, `<a>`) whenever possible.
*   **ARIA Attributes**: Use `aria-*` attributes only when semantic HTML is insufficient.
*   **Keyboard Navigation**: Ensure all interactive elements are keyboard accessible and have proper focus management.
*   **React Testing Library**: Use `RTL` to test component behavior, not implementation details.

### ❌ BAD: Non-semantic HTML / Untestable implementation
```tsx
// ❌ Div acting as a button, missing keyboard interaction
function MyButton() {
  return <div onClick={() => alert('Clicked!')}>Click Me</div>;
}

// ❌ Testing internal state or component instance (implementation detail)
test('MyComponent sets count to 1', () => {
  const { instance } = render(<MyComponent />);
  expect(instance.state.count).toBe(1); // ❌ Avoid
});
```

### ✅ GOOD: Semantic HTML / User-centric testing
```tsx
import { render, screen, fireEvent } from '@testing-library/react';

// ✅ Proper button element with click handler
function MyButton() {
  return <button type="button" onClick={() => alert('Clicked!')}>Click Me</button>;
}

// ✅ Test user interaction and visible output
test('MyButton alerts on click', () => {
  render(<MyButton />);
  fireEvent.click(screen.getByRole('button', { name: /click me/i }));
  expect(window.alert).toHaveBeenCalledWith('Clicked!'); // Assuming alert is mocked
});
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Фронтенд и UI» →

Сначала — react от других авторов.

react PatrickJS Правило задаёт агенту Cursor соглашения по React: структура компонентов, хуки, состояние, формы и доступность. Пригодится, когда в проекте много .tsx и .jsx и хочется единый стиль. ★ 41 011звёзд репо typescript-react-patterns agent-skills Скилл с 33 правилами типизации React на TypeScript: пропсы, хуки, события, refs, дженерики и контекст. Пригодится, когда агент пишет компоненты и лезет в типы. CX Codex +1 1 100установок react-component-architecture aj-geddes Скилл задаёт агенту правила проектирования React-компонентов: функциональные компоненты, хуки, композиция и TypeScript. Пригодится, когда растёт библиотека переиспользуемых компонентов. CX Codex +1 674установок react-router-v7 existential-birds Скилл с практиками React Router v7: подсказывает, когда брать loader, Form или fetcher, и как настраивать вложенные маршруты. CX Codex +1 572установок react-patterns affaan-m Скилл для Claude и других ИИ-редакторов: подсказывает, как писать компоненты React 18/19 — хуки, границы серверных и клиентских компонентов, формы, загрузку данных. CX Codex +1 4 900установок react-server-components patterns.dev Скилл объясняет React Server Components: какие компоненты рендерить на сервере и где ставить 'use client'. Пригодится в Next.js App Router. CX Codex +1 954установок gsap-react Bbeierle12 Скилл с готовыми шаблонами GSAP для React: хук useGSAP, работа с ref и очистка анимаций при размонтировании. CX Codex +1 724установок

Из того же набора69

sentry Правило задаёт, как инициализировать Sentry в проекте: где ставить SDK, какие переменные окружения использовать, как не сломать чужой код. ★ 3 579звёзд репо scikit-image Правило задаёт команде единый стиль работы с scikit-image: неизменяемость входных массивов, float-диапазон [0, 1], векторизация вместо циклов по пикселям. ★ 3 579звёзд репо ruby Правило для Cursor задаёт команде единый стиль Ruby: RuboCop, соглашения Rails, работа с N+1 и защита от SQL-инъекций. ★ 3 579звёзд репо riverpod Правило для Cursor задаёт команде единый стиль работы с Riverpod в Flutter: где держать провайдеры, когда ref.watch, а когда ref.read. ★ 3 579звёзд репо react-native Правило задаёт обязательные практики для React Native: feature-first структуру, функциональные компоненты, хуки и типизацию. Пригодится, когда проект растёт и файлы расползаются. ★ 3 579звёзд репо qwik Правило Cursor, которое подсказывает агенту, как писать Qwik-приложения: component$, useStore, QRL с суффиксом $ и загрузка данных через loader$. ★ 3 579звёзд репо pyramid Правило для Cursor с набором практик по Python-фреймворку Pyramid: структура проекта, конфигурация, транзакции и предикаты представлений. ★ 3 579звёзд репо pygame Правило для Cursor задаёт каркас Pygame-проекта: один UIManager, фиксированный шаг времени, вёрстка на якорях и темы в JSON. ★ 3 579звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой