diff --git a/.claude/rules/use-memo-directive.md b/.claude/rules/use-memo-directive.md new file mode 100644 index 0000000000..19f0817384 --- /dev/null +++ b/.claude/rules/use-memo-directive.md @@ -0,0 +1,43 @@ +--- +description: When writing or editing React components or custom hooks +--- + +# 'use memo' Directive Rule + +Always place `'use memo'` at the very top of the function body for **both React components and custom hooks** (`use*` functions). + +## Why + +This project uses the React Compiler in annotation mode (`babel-plugin-react-compiler`). The `'use memo'` directive opts the function in to full compiler optimization — automatic memoization of values, callbacks, and JSX without manual `useMemo`/`useCallback`. Omitting it from hooks means the hook's internals are not optimized, even if the components consuming it are. + +## Pattern + +```tsx +// ✅ Component — always add 'use memo' +function MyComponent({ id }: Props) { + 'use memo'; + + return
{id}
; +} + +// ✅ Custom hook — always add 'use memo' +const useMyData = (id: string) => { + 'use memo'; + + return useQuery(id); +}; + +// ❌ Missing in hook — not optimized +const useMyData = (id: string) => { + return useQuery(id); +}; +``` + +## Rules + +1. Add `'use memo'` as the **first statement** in the function body — before any hooks, variables, or logic. +2. Apply to **both components and custom hooks** (`use*` naming convention). +3. Comments before the directive are allowed. +4. Use single or double quotes — **not backticks**. +5. **Never remove** an existing `'use memo'` directive. +6. Do not add `'use memo'` inside helper functions that are not components or hooks (plain utilities, event handlers, etc.). diff --git a/.github/instructions/react.instructions.md b/.github/instructions/react.instructions.md index 22090247ee..69251ad507 100644 --- a/.github/instructions/react.instructions.md +++ b/.github/instructions/react.instructions.md @@ -8,10 +8,10 @@ These instructions apply to React components in the `/react` directory. ## React Compiler Optimization -### 'use memo' Directive (Recommended) +### 'use memo' Directive (Required) - This project uses the new **React Compiler**. -- We actively use React directives such as `use memo` and `use client` at the top components (NOT files). +- We actively use React directives such as `use memo` and `use client` at the top of **component and custom hook** function bodies (NOT files). - `use memo` is **intentional and valid** in this codebase. - Even if tooling or TypeScript/ESLint shows something like: - `Unknown directive: 'use memo'.` @@ -20,8 +20,8 @@ These instructions apply to React components in the `/react` directory. ### What should do -- When generating or editing React components: - - Prefer adding `use memo` when it is beneficial for React Compiler. +- When generating or editing React components **or custom hooks** (`use*` functions): + - **Always** add `'use memo'` at the top of the function body. - **Never** remove existing `use memo` directives. - **Never** “fix” or “rename” `use memo` to something else. - **Never** add comments suggesting that `use memo` is unknown, invalid, or deprecated. @@ -37,7 +37,7 @@ The `'use memo'` directive has **strict placement requirements**: - Only the first directive is processed; additional directives are ignored ```typescript -// ✅ Good: 'use memo' at the very beginning of function body +// ✅ Good: 'use memo' at the very beginning of component body function MyComponent({ data }: Props) { 'use memo'; @@ -46,6 +46,14 @@ function MyComponent({ data }: Props) { return
{data}
; } +// ✅ Good: 'use memo' in custom hooks too +const useMyHook = (id: string) => { + 'use memo'; + + const [value, setValue] = useState(null); + return value; +}; + // ✅ Good: Comments before 'use memo' are OK const AnotherComponent: React.FC = ({ data }) => { // This component is optimized by React Compiler @@ -74,6 +82,12 @@ function BacktickBad({ data }: Props) { `use memo`; // ❌ Must use quotes, not backticks return
{data}
; } + +// ❌ Bad: Missing 'use memo' in a new custom hook +function useData(id: string) { + // ❌ Should have 'use memo' at the top + return useSomeQuery(id); +} ``` ### Manual Optimization Hooks (Use Sparingly) @@ -1056,7 +1070,7 @@ When reviewing React code, check for: ### React Compiler & Optimization -- [ ] Component uses `'use memo'` directive if it's a new component +- [ ] Component and custom hook (`use*`) uses `'use memo'` directive if new - [ ] No unnecessary `useMemo`/`useCallback` (prefer 'use memo' directive) - [ ] `useEffectEvent` is used for non-reactive logic in Effects when appropriate