0% found this document useful (0 votes)
4 views5 pages

Comp Pattern

The document outlines modern React component architecture focusing on type safety, lazy loading, and Suspense boundaries. It emphasizes using the React.FC<Props> pattern for components, lazy loading heavy components, and implementing SuspenseLoader for a consistent loading experience. Additionally, it provides a recommended structure template for organizing component code effectively.

Uploaded by

westheryu
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views5 pages

Comp Pattern

The document outlines modern React component architecture focusing on type safety, lazy loading, and Suspense boundaries. It emphasizes using the React.FC<Props> pattern for components, lazy loading heavy components, and implementing SuspenseLoader for a consistent loading experience. Additionally, it provides a recommended structure template for organizing component code effectively.

Uploaded by

westheryu
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

# Component Patterns

Modern React component architecture for the application emphasizing type safety,
lazy loading, and Suspense boundaries.

---

## [Link] Pattern (PREFERRED)

### Why [Link]

All components use the `[Link]<Props>` pattern for:


- Explicit type safety for props
- Consistent component signatures
- Clear prop interface documentation
- Better IDE autocomplete

### Basic Pattern

```typescript
import React from 'react';

interface MyComponentProps {
/** User ID to display */
userId: number;
/** Optional callback when action occurs */
onAction?: () => void;
}

export const MyComponent: [Link]<MyComponentProps> = ({ userId, onAction }) => {


return (
<div>
User: {userId}
</div>
);
};

export default MyComponent;


```

**Key Points:**
- Props interface defined separately with JSDoc comments
- `[Link]<Props>` provides type safety
- Destructure props in parameters
- Default export at bottom

---

## Lazy Loading Pattern

### When to Lazy Load

Lazy load components that are:


- Heavy (DataGrid, charts, rich text editors)
- Route-level components
- Modal/dialog content (not shown initially)
- Below-the-fold content

### How to Lazy Load


```typescript
import React from 'react';

// Lazy load heavy component


const PostDataGrid = [Link](() =>
import('./grids/PostDataGrid')
);

// For named exports


const MyComponent = [Link](() =>
import('./MyComponent').then(module => ({
default: [Link]
}))
);
```

**Example from [Link]:**

```typescript
/**
* Main post table container component
*/
import React, { useState, useCallback } from 'react';
import { Box, Paper } from '@mui/material';

// Lazy load PostDataGrid to optimize bundle size


const PostDataGrid = [Link](() => import('./grids/PostDataGrid'));

import { SuspenseLoader } from '~components/SuspenseLoader';

export const PostTable: [Link]<PostTableProps> = ({ formId }) => {


return (
<Box>
<SuspenseLoader>
<PostDataGrid formId={formId} />
</SuspenseLoader>
</Box>
);
};

export default PostTable;


```

---

## Suspense Boundaries

### SuspenseLoader Component

**Import:**
```typescript
import { SuspenseLoader } from '~components/SuspenseLoader';
// Or
import { SuspenseLoader } from '@/components/SuspenseLoader';
```

**Usage:**
```typescript
<SuspenseLoader>
<LazyLoadedComponent />
</SuspenseLoader>
```

**What it does:**
- Shows loading indicator while lazy component loads
- Smooth fade-in animation
- Consistent loading experience
- Prevents layout shift

### Where to Place Suspense Boundaries

**Route Level:**
```typescript
// routes/my-route/[Link]
const MyPage = lazy(() => import('@/features/my-feature/components/MyPage'));

function Route() {
return (
<SuspenseLoader>
<MyPage />
</SuspenseLoader>
);
}
```

**Component Level:**
```typescript
function ParentComponent() {
return (
<Box>
<Header />
<SuspenseLoader>
<HeavyDataGrid />
</SuspenseLoader>
</Box>
);
}
```

**Multiple Boundaries:**
```typescript
function Page() {
return (
<Box>
<SuspenseLoader>
<HeaderSection />
</SuspenseLoader>

<SuspenseLoader>
<MainContent />
</SuspenseLoader>

<SuspenseLoader>
<Sidebar />
</SuspenseLoader>
</Box>
);
}
```

Each section loads independently, better UX.

---

## Component Structure Template

### Recommended Order

```typescript
/**
* Component description
* What it does, when to use it
*/
import React, { useState, useCallback, useMemo, useEffect } from 'react';
import { Box, Paper, Button } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
import { useSuspenseQuery } from '@tanstack/react-query';

// Feature imports
import { myFeatureApi } from '../api/myFeatureApi';
import type { MyData } from '~types/myData';

// Component imports
import { SuspenseLoader } from '~components/SuspenseLoader';

// Hooks
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';

// 1. PROPS INTERFACE (with JSDoc)


interface MyComponentProps {
/** The ID of the entity to display */
entityId: number;
/** Optional callback when action completes */
onComplete?: () => void;
/** Display mode */
mode?: 'view' | 'edit';
}

// 2. STYLES (if inline and <100 lines)


const componentStyles: Record<string, SxProps<Theme>> = {
container: {
p: 2,
display: 'flex',
flexDirection: 'column',
},
header: {
mb: 2,
display: 'flex',
justifyContent: 'space-between',
},
};

// 3. COMPONENT DEFINITION
export const MyComponent: [Link]<MyComponentProps> = ({
entityId,
onComplete,
mode = 'view',
}) => {
// 4. HOOKS (in this order)
// - Context hooks first
const { user } = useAuth();
const { showSuccess, showError } = useMuiSnackbar();

// - Data fetching
const { data } = useSuspenseQuery({
queryKey: ['myEntity', entityId],
queryFn: () => [Link](entityId),
});

You might also like