@@ -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+
3657Always consider React composability when writing or reviewing components:
3758
38591 . ** Single Responsibility**
60+
3961 - Each component should do one thing well
4062 - Extract complex logic into smaller, focused components
4163
42642 . ** 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
47703 . ** 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+
90115We 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+
154181If 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
222255const 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+
249284When 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
326367interface MyComponentProps extends BAIModalProps {
327368 customProp: string ;
328- variant: ' primary' | ' secondary' ;
369+ variant: " primary" | " secondary" ;
329370}
330371
331372// ✅ Good: Discriminated unions
332373type 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
375419const 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
412460When 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