@qlover/create-app 0.7.14 → 0.7.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/README.en.md +131 -0
- package/dist/templates/next-app/README.md +115 -20
- package/dist/templates/next-app/docs/en/api.md +387 -0
- package/dist/templates/next-app/docs/en/component.md +544 -0
- package/dist/templates/next-app/docs/en/database.md +496 -0
- package/dist/templates/next-app/docs/en/development-guide.md +727 -0
- package/dist/templates/next-app/docs/en/env.md +563 -0
- package/dist/templates/next-app/docs/en/i18n.md +287 -0
- package/dist/templates/next-app/docs/en/index.md +166 -0
- package/dist/templates/next-app/docs/en/page.md +457 -0
- package/dist/templates/next-app/docs/en/project-structure.md +177 -0
- package/dist/templates/next-app/docs/en/router.md +427 -0
- package/dist/templates/next-app/docs/en/theme.md +532 -0
- package/dist/templates/next-app/docs/en/validator.md +478 -0
- package/dist/templates/next-app/docs/zh/api.md +387 -0
- package/dist/templates/next-app/docs/zh/component.md +544 -0
- package/dist/templates/next-app/docs/zh/database.md +496 -0
- package/dist/templates/next-app/docs/zh/development-guide.md +727 -0
- package/dist/templates/next-app/docs/zh/env.md +563 -0
- package/dist/templates/next-app/docs/zh/i18n.md +287 -0
- package/dist/templates/next-app/docs/zh/index.md +166 -0
- package/dist/templates/next-app/docs/zh/page.md +457 -0
- package/dist/templates/next-app/docs/zh/project-structure.md +177 -0
- package/dist/templates/next-app/docs/zh/router.md +427 -0
- package/dist/templates/next-app/docs/zh/theme.md +532 -0
- package/dist/templates/next-app/docs/zh/validator.md +476 -0
- package/package.json +1 -1
- package/dist/templates/next-app/docs/env.md +0 -94
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
# Component Development and State Management Guide
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [Component Architecture Overview](#component-architecture-overview)
|
|
6
|
+
2. [Component Architecture and Design Principles](#component-architecture-and-design-principles)
|
|
7
|
+
3. [State Management System](#state-management-system)
|
|
8
|
+
4. [Component Communication and Event Handling](#component-communication-and-event-handling)
|
|
9
|
+
5. [Component Testing and Performance Optimization](#component-testing-and-performance-optimization)
|
|
10
|
+
6. [Best Practices and Examples](#best-practices-and-examples)
|
|
11
|
+
|
|
12
|
+
## Component Architecture Overview
|
|
13
|
+
|
|
14
|
+
### 1. Overall Architecture
|
|
15
|
+
|
|
16
|
+
The project adopts a layered component architecture design:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Component Layer State Layer
|
|
20
|
+
┌──────────────┐ ┌──────────────┐
|
|
21
|
+
│ UI Components│ │State Interface│
|
|
22
|
+
├──────────────┤ ├──────────────┤
|
|
23
|
+
│ Containers │ ◄─────┤State Implement│
|
|
24
|
+
├──────────────┤ ├──────────────┤
|
|
25
|
+
│ Business │ │State Actions │
|
|
26
|
+
└──────────────┘ └──────────────┘
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Core Concepts
|
|
30
|
+
|
|
31
|
+
- **UI Components**: Pure presentation components, no business logic
|
|
32
|
+
- **Container Components**: Responsible for state management and business logic
|
|
33
|
+
- **Business Components**: Components for specific business scenarios
|
|
34
|
+
- **State Management**: Store pattern-based state management system
|
|
35
|
+
|
|
36
|
+
### 3. Technology Stack
|
|
37
|
+
|
|
38
|
+
- **React + Next.js**: Base framework
|
|
39
|
+
- **TypeScript**: Type system
|
|
40
|
+
- **Inversify**: Dependency injection
|
|
41
|
+
- **Ant Design**: UI component library
|
|
42
|
+
- **Tailwind CSS**: Styling system
|
|
43
|
+
|
|
44
|
+
## Component Architecture and Design Principles
|
|
45
|
+
|
|
46
|
+
### 1. Component Categories
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// 1. UI Component
|
|
50
|
+
export function Button({ onClick, children }: ButtonProps) {
|
|
51
|
+
return (
|
|
52
|
+
<button
|
|
53
|
+
onClick={onClick}
|
|
54
|
+
className="px-4 py-2 bg-primary text-white rounded"
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</button>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 2. Container Component
|
|
62
|
+
export function UserProfileContainer() {
|
|
63
|
+
const userStore = useIOC(UserStore);
|
|
64
|
+
const user = useStore(userStore, userStore.selector.user);
|
|
65
|
+
|
|
66
|
+
return <UserProfile user={user} />;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 3. Business Component
|
|
70
|
+
export function LoginForm({ tt }: { tt: LoginI18nInterface }) {
|
|
71
|
+
const userService = useIOC(I.UserServiceInterface);
|
|
72
|
+
|
|
73
|
+
const handleLogin = async (values: LoginFormData) => {
|
|
74
|
+
await userService.login(values);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Form onFinish={handleLogin}>
|
|
79
|
+
{/* Form content */}
|
|
80
|
+
</Form>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 2. Component Providers
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// Combine multiple providers
|
|
89
|
+
export function ComboProvider({
|
|
90
|
+
themeConfig,
|
|
91
|
+
children
|
|
92
|
+
}: Props) {
|
|
93
|
+
const mounted = useMountedClient();
|
|
94
|
+
const IOC = clientIOC.create();
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<AntdThemeProvider theme={themeConfig.antdTheme}>
|
|
98
|
+
<ThemeProvider
|
|
99
|
+
themes={themeConfig.supportedThemes}
|
|
100
|
+
defaultTheme={themeConfig.defaultTheme}
|
|
101
|
+
>
|
|
102
|
+
<BootstrapsProvider>
|
|
103
|
+
<AntdRegistry>
|
|
104
|
+
{mounted ? children : null}
|
|
105
|
+
</AntdRegistry>
|
|
106
|
+
</BootstrapsProvider>
|
|
107
|
+
</ThemeProvider>
|
|
108
|
+
</AntdThemeProvider>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 3. Component Interface Design
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// 1. Component interface definition
|
|
117
|
+
interface ChatComponentInterface {
|
|
118
|
+
// Property definitions
|
|
119
|
+
messages: MessageInterface[];
|
|
120
|
+
loading?: boolean;
|
|
121
|
+
|
|
122
|
+
// Event handlers
|
|
123
|
+
onSend: (message: string) => void;
|
|
124
|
+
onClear: () => void;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 2. Component implementation
|
|
128
|
+
@injectable()
|
|
129
|
+
export class ChatComponent implements ChatComponentInterface {
|
|
130
|
+
constructor(
|
|
131
|
+
@inject(ChatStore) private store: ChatStoreInterface,
|
|
132
|
+
@inject(I.Logger) private logger: LoggerInterface
|
|
133
|
+
) {}
|
|
134
|
+
|
|
135
|
+
// Implement interface methods
|
|
136
|
+
async onSend(message: string) {
|
|
137
|
+
try {
|
|
138
|
+
await this.store.sendMessage(message);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
this.logger.error('Failed to send message:', error);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## State Management System
|
|
147
|
+
|
|
148
|
+
### 1. State Interfaces
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// 1. State interface definition
|
|
152
|
+
export interface StoreStateInterface {
|
|
153
|
+
readonly loading?: boolean;
|
|
154
|
+
readonly error?: Error | null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 2. Async state interface
|
|
158
|
+
export interface AsyncStateInterface<T> {
|
|
159
|
+
loading: boolean;
|
|
160
|
+
result: T | null;
|
|
161
|
+
error: unknown | null;
|
|
162
|
+
startTime: number;
|
|
163
|
+
endTime: number;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 3. Request state implementation
|
|
167
|
+
export class RequestState<T = unknown> implements AsyncStateInterface<T> {
|
|
168
|
+
startTime: number;
|
|
169
|
+
endTime: number;
|
|
170
|
+
|
|
171
|
+
constructor(
|
|
172
|
+
public loading: boolean = false,
|
|
173
|
+
public result: T | null = null,
|
|
174
|
+
public error: unknown | null = null
|
|
175
|
+
) {
|
|
176
|
+
this.startTime = Date.now();
|
|
177
|
+
this.endTime = 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
end(): this {
|
|
181
|
+
this.endTime = Date.now();
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 2. Store Implementation
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// 1. Store base class
|
|
191
|
+
export abstract class StoreInterface<State extends StoreStateInterface> {
|
|
192
|
+
protected state: State;
|
|
193
|
+
protected subscribers: Set<(state: State) => void>;
|
|
194
|
+
|
|
195
|
+
constructor(initialState: () => State) {
|
|
196
|
+
this.state = initialState();
|
|
197
|
+
this.subscribers = new Set();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// State update
|
|
201
|
+
protected emit(newState: State): void {
|
|
202
|
+
this.state = newState;
|
|
203
|
+
this.subscribers.forEach((subscriber) => subscriber(this.state));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Selectors
|
|
207
|
+
selector = {
|
|
208
|
+
loading: (state: State) => state.loading,
|
|
209
|
+
error: (state: State) => state.error
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 2. Concrete Store implementation
|
|
214
|
+
@injectable()
|
|
215
|
+
export class UserStore extends StoreInterface<UserState> {
|
|
216
|
+
constructor(@inject(UserService) private userService: UserServiceInterface) {
|
|
217
|
+
super(() => ({
|
|
218
|
+
user: null,
|
|
219
|
+
loading: false,
|
|
220
|
+
error: null
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async fetchUser(id: string) {
|
|
225
|
+
this.emit({ ...this.state, loading: true });
|
|
226
|
+
try {
|
|
227
|
+
const user = await this.userService.getUser(id);
|
|
228
|
+
this.emit({ ...this.state, user, loading: false });
|
|
229
|
+
} catch (error) {
|
|
230
|
+
this.emit({ ...this.state, error, loading: false });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 3. State Usage
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// 1. Using Store in components
|
|
240
|
+
export function UserProfile() {
|
|
241
|
+
const userStore = useIOC(UserStore);
|
|
242
|
+
const user = useStore(userStore, userStore.selector.user);
|
|
243
|
+
const loading = useStore(userStore, userStore.selector.loading);
|
|
244
|
+
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
userStore.fetchUser(userId);
|
|
247
|
+
}, [userStore, userId]);
|
|
248
|
+
|
|
249
|
+
if (loading) return <Loading />;
|
|
250
|
+
if (!user) return <NotFound />;
|
|
251
|
+
|
|
252
|
+
return <UserInfo user={user} />;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// 2. Combining multiple Stores
|
|
256
|
+
export function Dashboard() {
|
|
257
|
+
const userStore = useIOC(UserStore);
|
|
258
|
+
const statsStore = useIOC(StatsStore);
|
|
259
|
+
|
|
260
|
+
const user = useStore(userStore, userStore.selector.user);
|
|
261
|
+
const stats = useStore(statsStore, statsStore.selector.stats);
|
|
262
|
+
|
|
263
|
+
return (
|
|
264
|
+
<div>
|
|
265
|
+
<UserWidget user={user} />
|
|
266
|
+
<StatsWidget stats={stats} />
|
|
267
|
+
</div>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Component Communication and Event Handling
|
|
273
|
+
|
|
274
|
+
### 1. Event Handling
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// 1. Define event interface
|
|
278
|
+
interface ChatEvents {
|
|
279
|
+
onSend: (message: string) => void;
|
|
280
|
+
onClear: () => void;
|
|
281
|
+
onError: (error: Error) => void;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// 2. Implement event handling
|
|
285
|
+
export function ChatComponent({ onSend, onClear, onError }: ChatEvents) {
|
|
286
|
+
const handleSend = useCallback(async (message: string) => {
|
|
287
|
+
try {
|
|
288
|
+
await onSend(message);
|
|
289
|
+
} catch (error) {
|
|
290
|
+
onError(error as Error);
|
|
291
|
+
}
|
|
292
|
+
}, [onSend, onError]);
|
|
293
|
+
|
|
294
|
+
return (
|
|
295
|
+
<div>
|
|
296
|
+
<ChatInput onSend={handleSend} />
|
|
297
|
+
<ClearButton onClick={onClear} />
|
|
298
|
+
</div>
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 2. Component Communication
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
// 1. Through props
|
|
307
|
+
export function ParentComponent() {
|
|
308
|
+
const [data, setData] = useState<Data>();
|
|
309
|
+
|
|
310
|
+
return (
|
|
311
|
+
<ChildComponent
|
|
312
|
+
data={data}
|
|
313
|
+
onUpdate={setData}
|
|
314
|
+
/>
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 2. Through Context
|
|
319
|
+
const ThemeContext = createContext<Theme>(defaultTheme);
|
|
320
|
+
|
|
321
|
+
export function ThemeProvider({ children }: PropsWithChildren) {
|
|
322
|
+
const [theme, setTheme] = useState(defaultTheme);
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<ThemeContext.Provider value={{ theme, setTheme }}>
|
|
326
|
+
{children}
|
|
327
|
+
</ThemeContext.Provider>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Component Testing and Performance Optimization
|
|
333
|
+
|
|
334
|
+
### 1. Component Testing
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
// 1. Unit testing
|
|
338
|
+
describe('UserProfile', () => {
|
|
339
|
+
it('should render user info', () => {
|
|
340
|
+
const user = { id: '1', name: 'Test' };
|
|
341
|
+
render(<UserProfile user={user} />);
|
|
342
|
+
|
|
343
|
+
expect(screen.getByText(user.name)).toBeInTheDocument();
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('should handle loading state', () => {
|
|
347
|
+
render(<UserProfile loading />);
|
|
348
|
+
expect(screen.getByTestId('loading')).toBeInTheDocument();
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// 2. Integration testing
|
|
353
|
+
describe('LoginForm', () => {
|
|
354
|
+
it('should handle login flow', async () => {
|
|
355
|
+
const mockLogin = jest.fn();
|
|
356
|
+
const { getByLabelText, getByRole } = render(
|
|
357
|
+
<LoginForm onLogin={mockLogin} />
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
await userEvent.type(getByLabelText('Email'), 'test@example.com');
|
|
361
|
+
await userEvent.type(getByLabelText('Password'), 'password');
|
|
362
|
+
await userEvent.click(getByRole('button', { name: 'Login' }));
|
|
363
|
+
|
|
364
|
+
expect(mockLogin).toHaveBeenCalledWith({
|
|
365
|
+
email: 'test@example.com',
|
|
366
|
+
password: 'password'
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### 2. Performance Optimization
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
// 1. Using memo for render optimization
|
|
376
|
+
const UserCard = memo(function UserCard({ user }: UserCardProps) {
|
|
377
|
+
return (
|
|
378
|
+
<div>
|
|
379
|
+
<h3>{user.name}</h3>
|
|
380
|
+
<p>{user.email}</p>
|
|
381
|
+
</div>
|
|
382
|
+
);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
// 2. Using useMemo and useCallback
|
|
386
|
+
function UserList({ users }: UserListProps) {
|
|
387
|
+
const sortedUsers = useMemo(() => {
|
|
388
|
+
return [...users].sort((a, b) => a.name.localeCompare(b.name));
|
|
389
|
+
}, [users]);
|
|
390
|
+
|
|
391
|
+
const handleUserClick = useCallback((userId: string) => {
|
|
392
|
+
// Handle user click
|
|
393
|
+
}, []);
|
|
394
|
+
|
|
395
|
+
return (
|
|
396
|
+
<div>
|
|
397
|
+
{sortedUsers.map(user => (
|
|
398
|
+
<UserCard
|
|
399
|
+
key={user.id}
|
|
400
|
+
user={user}
|
|
401
|
+
onClick={handleUserClick}
|
|
402
|
+
/>
|
|
403
|
+
))}
|
|
404
|
+
</div>
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Best Practices and Examples
|
|
410
|
+
|
|
411
|
+
### 1. Component Design Principles
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
// 1. Single Responsibility Principle
|
|
415
|
+
// ❌ Wrong: Too many responsibilities
|
|
416
|
+
function UserCard({ user, onEdit, onDelete, onShare }) {
|
|
417
|
+
return (
|
|
418
|
+
<div>
|
|
419
|
+
<UserInfo user={user} />
|
|
420
|
+
<UserActions user={user} />
|
|
421
|
+
<SocialSharing user={user} />
|
|
422
|
+
</div>
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// ✅ Correct: Split into focused components
|
|
427
|
+
function UserCard({ user }) {
|
|
428
|
+
return <UserInfo user={user} />;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function UserActions({ user }) {
|
|
432
|
+
return (
|
|
433
|
+
<div>
|
|
434
|
+
<EditButton user={user} />
|
|
435
|
+
<DeleteButton user={user} />
|
|
436
|
+
</div>
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// 2. Composition over Inheritance
|
|
441
|
+
// ❌ Wrong: Using inheritance
|
|
442
|
+
class SpecialButton extends Button {
|
|
443
|
+
render() {
|
|
444
|
+
return <button className="special">{this.props.children}</button>;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// ✅ Correct: Using composition
|
|
449
|
+
function Button({ variant, children, ...props }) {
|
|
450
|
+
return (
|
|
451
|
+
<button className={`btn-${variant}`} {...props}>
|
|
452
|
+
{children}
|
|
453
|
+
</button>
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### 2. State Management Best Practices
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
// 1. State isolation
|
|
462
|
+
@injectable()
|
|
463
|
+
export class UserStore extends StoreInterface<UserState> {
|
|
464
|
+
// Encapsulate state logic in Store
|
|
465
|
+
private async validateUser(user: User): Promise<boolean> {
|
|
466
|
+
return this.validator.validate(user);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
async updateUser(user: User) {
|
|
470
|
+
if (await this.validateUser(user)) {
|
|
471
|
+
this.emit({ ...this.state, user });
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// 2. Selector pattern
|
|
477
|
+
@injectable()
|
|
478
|
+
export class DashboardStore extends StoreInterface<DashboardState> {
|
|
479
|
+
selector = {
|
|
480
|
+
...super.selector,
|
|
481
|
+
activeUsers: (state: DashboardState) =>
|
|
482
|
+
state.users.filter((u) => u.isActive),
|
|
483
|
+
totalRevenue: (state: DashboardState) =>
|
|
484
|
+
state.transactions.reduce((sum, t) => sum + t.amount, 0)
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### 3. Performance Optimization Examples
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
// 1. Virtualized list
|
|
493
|
+
function VirtualizedList({ items }: Props) {
|
|
494
|
+
return (
|
|
495
|
+
<VirtualScroller
|
|
496
|
+
itemCount={items.length}
|
|
497
|
+
itemSize={50}
|
|
498
|
+
height={400}
|
|
499
|
+
width="100%"
|
|
500
|
+
>
|
|
501
|
+
{({ index, style }) => (
|
|
502
|
+
<div style={style}>
|
|
503
|
+
<ListItem item={items[index]} />
|
|
504
|
+
</div>
|
|
505
|
+
)}
|
|
506
|
+
</VirtualScroller>
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// 2. Lazy loading components
|
|
511
|
+
const LazyUserProfile = lazy(() => import('./UserProfile'));
|
|
512
|
+
|
|
513
|
+
function App() {
|
|
514
|
+
return (
|
|
515
|
+
<Suspense fallback={<Loading />}>
|
|
516
|
+
<LazyUserProfile />
|
|
517
|
+
</Suspense>
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
## Summary
|
|
523
|
+
|
|
524
|
+
The project's component and state management system follows these principles:
|
|
525
|
+
|
|
526
|
+
1. **Component Design**:
|
|
527
|
+
- Clear responsibility separation
|
|
528
|
+
- Reusable component interfaces
|
|
529
|
+
- Type-safe property definitions
|
|
530
|
+
|
|
531
|
+
2. **State Management**:
|
|
532
|
+
- Centralized state management
|
|
533
|
+
- Reactive state updates
|
|
534
|
+
- Type-safe state definitions
|
|
535
|
+
|
|
536
|
+
3. **Performance Optimization**:
|
|
537
|
+
- Component-level optimization
|
|
538
|
+
- State update optimization
|
|
539
|
+
- Resource loading optimization
|
|
540
|
+
|
|
541
|
+
4. **Best Practices**:
|
|
542
|
+
- Single Responsibility Principle
|
|
543
|
+
- Composition over Inheritance
|
|
544
|
+
- State Isolation Principle
|