Skip to content

Commit 7790fed

Browse files
committed
feat(FR-1634): Configure Copilot to accept 'use memo' React directive
1 parent dab66f2 commit 7790fed

File tree

1 file changed

+60
-11
lines changed

1 file changed

+60
-11
lines changed

.github/instructions/react.instructions.md

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,28 @@ These instructions apply to React components in the `/react` directory.
99
## React Compiler Optimization
1010

1111
### 'use memo' Directive (Recommended)
12-
- **Prefer using the `'use memo'` directive** at the top of new component files
13-
- React Compiler automatically optimizes memoization when this directive is present
14-
- This is the modern, recommended approach over manual optimization
12+
13+
- This project uses the new **React Compiler**.
14+
- We actively use React directives such as `use memo` and `use client` at the top of files or components.
15+
- `use memo` is **intentional and valid** in this codebase.
16+
- Even if tooling or TypeScript/ESLint shows something like:
17+
- `Unknown directive: 'use memo'.`
18+
- or similar warnings/errors
19+
these directives are still **correct and should not be removed or changed**.
20+
21+
### What should do
22+
23+
- When generating or editing React components:
24+
- Prefer adding `use memo` when it is beneficial for React Compiler.
25+
- Do **not** remove existing `use memo` directives.
26+
- Do **not** “fix” or “rename” `use memo` to something else.
27+
- Do **not** add comments suggesting that `use memo` is unknown, invalid, or deprecated.
28+
29+
### Code style for React files
30+
31+
- Keep React directives (`use memo`, `use client`, etc.) at the very top of the file or at the beginning of the component body, before other statements.
32+
- Do not wrap `use memo` in conditional logic or function calls; it must stay as a simple directive string.
33+
- When in doubt about `use memo`, assume it is correct and keep it as-is.
1534

1635
```typescript
1736
'use memo';
@@ -25,6 +44,7 @@ const MyComponent: React.FC<Props> = ({ data }) => {
2544
```
2645

2746
### Manual Optimization Hooks (Use Sparingly)
47+
2848
- `useMemo` and `useCallback` can still be used when needed
2949
- However, prefer `'use memo'` directive as React Compiler handles most cases automatically
3050
- Only use manual hooks when you have specific performance bottlenecks identified through profiling
@@ -33,18 +53,22 @@ const MyComponent: React.FC<Props> = ({ data }) => {
3353
## React Composability
3454

3555
### Component Composition Principles
56+
3657
Always consider React composability when writing or reviewing components:
3758

3859
1. **Single Responsibility**
60+
3961
- Each component should do one thing well
4062
- Extract complex logic into smaller, focused components
4163

4264
2. **Composition Over Props Drilling**
65+
4366
- Use component composition instead of passing props through multiple levels
4467
- Consider using Recoil for global state management
4568
- Leverage children props and render props patterns
4669

4770
3. **Reusability**
71+
4872
- Design components to be reusable across different contexts
4973
- Use generic prop types when appropriate
5074
- Avoid hard-coding values that could be props
@@ -87,7 +111,9 @@ const ComponentA = () => {
87111
## GraphQL/Relay Integration
88112

89113
### Commonly Used Hooks
114+
90115
We primarily use these Relay hooks:
116+
91117
- **`useLazyLoadQuery`** - Fetch data on component mount
92118
- **`useFragment`** - Read fragment data from parent query
93119
- **`useRefetchableFragment`** - Fragment with refetch capability
@@ -151,23 +177,28 @@ const UserList = ({ usersRef }) => {
151177
```
152178

153179
### Modern Relay Patterns (Recommended)
180+
154181
If applicable, consider these newer patterns:
182+
155183
- **`@required` directive** - Type-safe null handling in fragments
156184
- **`@alias` directive** - Rename fields for better semantics
157185
- **Suspense boundaries** - Better loading state handling with concurrent features
158186

159187
### Fragment Colocation
188+
160189
- Colocate GraphQL fragments with components that use them
161190
- Use Relay's fragment composition for nested data requirements
162191

163192
### Query Optimization
193+
164194
- Avoid over-fetching data - only request fields you need
165195
- Use Relay's pagination for lists (`usePaginationFragment`)
166196
- Consider using `@defer` and `@stream` for progressive loading
167197

168198
## Backend.AI UI Component Library
169199

170200
### Prefer BAI Components
201+
171202
- **Always prefer `backend.ai-ui` package components** over Ant Design equivalents
172203
- Use `BAIFlex`, `BAIModal`, `BAIButton`, etc. instead of Ant Design components
173204
- These components are custom-designed for Backend.AI WebUI
@@ -184,6 +215,7 @@ import { BAIModal, BAIFlex } from '@backend.ai/backend.ai-ui';
184215
```
185216

186217
### When to Use Ant Design
218+
187219
- Simple confirmation modals using App context
188220
- When BAI component equivalent doesn't exist
189221
- Temporary solutions while waiting for BAI component development
@@ -212,25 +244,27 @@ const MyComponent = () => {
212244
## Custom Utilities and Hooks
213245

214246
### useFetchKey Hook
247+
215248
- Check if `useFetchKey` is needed for data fetching patterns
216249
- This hook manages fetch keys for cache invalidation
217250
- Verify it's being used when component needs to refetch data
218251

219252
```typescript
220-
import { useFetchKey } from './hooks/useFetchKey';
253+
import { useFetchKey } from "./hooks/useFetchKey";
221254

222255
const MyComponent = () => {
223256
const [fetchKey, setFetchKey] = useFetchKey();
224257

225258
// Use fetchKey in queries to trigger refetch
226259
const { data } = useQuery({
227-
queryKey: ['data', fetchKey],
260+
queryKey: ["data", fetchKey],
228261
// ...
229262
});
230263
};
231264
```
232265

233266
### BAIUnmountAfterClose
267+
234268
- Check if `BAIUnmountAfterClose` is being used for modals/drawers with forms
235269
- This component ensures proper cleanup of form state when modal closes
236270
- Prevents stale data issues in modals
@@ -246,14 +280,17 @@ import { BAIUnmountAfterClose } from './components';
246280
```
247281

248282
### Code Review Checklist for Custom Utils
283+
249284
When reviewing code, verify:
285+
250286
- [ ] `useFetchKey` is used when data needs manual refetching
251287
- [ ] `BAIUnmountAfterClose` wraps modal/drawer content with forms
252288
- [ ] Custom hooks are properly utilized where they provide value
253289

254290
## Error Handling
255291

256292
### Error Boundaries
293+
257294
- **Always use pre-defined error boundary components**
258295
- `ErrorBoundaryWithNullFallback` - for silent error handling
259296
- `BAIErrorBoundary` - for user-facing error UI
@@ -274,13 +311,15 @@ import { ErrorBoundaryWithNullFallback, BAIErrorBoundary } from './components';
274311
```
275312

276313
### Loading States
314+
277315
- Always handle loading states in async operations
278316
- Use Suspense boundaries where appropriate
279317
- Provide skeleton loaders for better UX
280318

281319
## Ant Design (Secondary Usage)
282320

283321
### When BAI Components Are Not Available
322+
284323
- Use Ant Design components when no BAI equivalent exists
285324
- Prefer using App context (`App.useApp()`) for modals, messages, notifications
286325
- Access theme tokens via `theme.useToken()`
@@ -310,13 +349,15 @@ const MyComponent = () => {
310349
```
311350

312351
### Theme Awareness
352+
313353
- Components should work in both light and dark themes
314354
- Use theme tokens instead of hard-coded colors
315355
- Test components in both theme modes
316356

317357
## TypeScript Best Practices
318358

319359
### Type Safety
360+
320361
- Always define prop interfaces
321362
- Extend BAI/Ant Design's prop types when wrapping components
322363
- Use discriminated unions for variant props
@@ -325,17 +366,18 @@ const MyComponent = () => {
325366
// ✅ Good: Proper prop typing
326367
interface MyComponentProps extends BAIModalProps {
327368
customProp: string;
328-
variant: 'primary' | 'secondary';
369+
variant: "primary" | "secondary";
329370
}
330371

331372
// ✅ Good: Discriminated unions
332373
type Status =
333-
| { type: 'loading' }
334-
| { type: 'success'; data: Data }
335-
| { type: 'error'; error: Error };
374+
| { type: "loading" }
375+
| { type: "success"; data: Data }
376+
| { type: "error"; error: Error };
336377
```
337378

338379
### Generic Components
380+
339381
- Use generics for reusable components with different data types
340382
- Properly constrain generic types
341383

@@ -360,20 +402,22 @@ const List = <T,>({ items, renderItem }: ListProps<T>) => {
360402
## State Management
361403

362404
### Local State
405+
363406
- Use `useState` for component-local state
364407
- Use `useReducer` for complex state logic
365408

366409
### Global State
410+
367411
- Use **Recoil** for global state management
368412
- Use Relay for GraphQL-backed state
369413
- Use React Context for simple UI state that doesn't need persistence
370414

371415
```typescript
372416
// ✅ Good: Recoil for global state
373-
import { atom, useRecoilState } from 'recoil';
417+
import { atom, useRecoilState } from "recoil";
374418

375419
const userSettingsState = atom({
376-
key: 'userSettings',
420+
key: "userSettings",
377421
default: {},
378422
});
379423

@@ -386,30 +430,35 @@ const Component = () => {
386430
## Testing
387431

388432
### Component Tests
433+
389434
- Write tests for complex component logic
390435
- Test user interactions, not implementation details
391436
- Use React Testing Library conventions
392437

393438
### Accessibility in Tests
439+
394440
- Query by accessible roles and labels
395441
- Ensure keyboard navigation works
396442
- Test with screen reader expectations
397443

398444
## Performance
399445

400446
### Code Splitting
447+
401448
- Lazy load heavy components with `React.lazy()`
402449
- Split routes at page boundaries
403450
- Monitor bundle sizes
404451

405452
### Rendering Optimization
453+
406454
- Prefer `'use memo'` directive for new components
407455
- Use `React.memo()` for expensive pure components only when profiling shows benefit
408456
- Avoid premature optimization
409457

410458
## Code Review Checklist
411459

412460
When reviewing React code, check for:
461+
413462
- [ ] Component uses `'use memo'` directive if it's a new component
414463
- [ ] Component follows composability principles (no props drilling, proper extraction)
415464
- [ ] No unnecessary `useMemo`/`useCallback` (prefer 'use memo' directive)

0 commit comments

Comments
 (0)