refactor: optimize component rendering with memoization and improve state management

- Added memoization to ChatHistoryPanel, ChatMessageList, and TaskBoard components to prevent unnecessary re-renders.
- Refactored HomePage to utilize useMemo for derived state calculations, enhancing performance.
- Updated main.tsx to conditionally render React.StrictMode based on the environment.
- Improved chat and channel store hooks to allow for selector functions, enhancing flexibility in state selection.
- Enhanced streaming message handling in chat store to manage pending deltas more effectively.
- Refactored LoginPage to include animated decorations for improved user experience.
- Implemented lazy loading for routes in the router to optimize initial load time.
This commit is contained in:
duanshuwen
2026-04-18 11:05:49 +08:00
parent 85d92b937f
commit dfa4388087
12 changed files with 533 additions and 189 deletions

View File

@@ -1,4 +1,4 @@
import { useEffect, useRef, useState } from 'react';
import { memo, useEffect, useRef, useState } from 'react';
import type { ChatHistoryBucket } from './types';
import {
ChevronDown,
@@ -31,7 +31,7 @@ function cx(...classes: Array<string | false | null | undefined>): string {
return classes.filter(Boolean).join(' ');
}
export default function ChatHistoryPanel({
function ChatHistoryPanel({
buckets,
selectedConversationId,
loading,
@@ -50,12 +50,17 @@ export default function ChatHistoryPanel({
useEffect(() => {
setCollapsedBuckets((current) => {
const next: Record<string, boolean> = {};
const currentKeys = Object.keys(current);
let changed = currentKeys.length !== buckets.length;
for (const bucket of buckets) {
next[bucket.key] = current[bucket.key] ?? false;
if (current[bucket.key] !== next[bucket.key]) {
changed = true;
}
}
return next;
return changed ? next : current;
});
}, [buckets]);
@@ -299,3 +304,5 @@ export default function ChatHistoryPanel({
</aside>
);
}
export default memo(ChatHistoryPanel);

View File

@@ -1,4 +1,4 @@
import { useEffect, useRef } from 'react';
import { memo, useEffect, useRef } from 'react';
import type { ChatMessageItem } from './types';
type ChatMessageListProps = {
@@ -6,7 +6,7 @@ type ChatMessageListProps = {
loading?: boolean;
};
export default function ChatMessageList({ messages, loading }: ChatMessageListProps) {
function ChatMessageList({ messages, loading }: ChatMessageListProps) {
const containerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
@@ -90,3 +90,5 @@ export default function ChatMessageList({ messages, loading }: ChatMessageListPr
</div>
);
}
export default memo(ChatMessageList);

View File

@@ -1,3 +1,4 @@
import { memo } from 'react';
import type { TaskItem } from './types';
type TaskBoardProps = {
@@ -11,7 +12,7 @@ type TaskBoardProps = {
currentTime?: string;
};
export default function TaskBoard({
function TaskBoard({
activeTab,
pendingItems,
completedItems,
@@ -112,3 +113,11 @@ export default function TaskBoard({
</aside>
);
}
export default memo(TaskBoard, (prevProps, nextProps) => (
prevProps.activeTab === nextProps.activeTab
&& prevProps.pendingItems === nextProps.pendingItems
&& prevProps.completedItems === nextProps.completedItems
&& prevProps.currentDateLabel === nextProps.currentDateLabel
&& prevProps.currentTime === nextProps.currentTime
));