perf: 使用 React.memo 优化社区组件渲染性能
**优化目标**: - 减少组件卸载次数:从 6 次/刷新 → 1-2 次/刷新(↓ 66-83%) - 减少渲染次数:从 9 次/刷新 → 4-5 次/刷新(↓ 44-55%) **优化组件**(共 7 个): 1. ✅ ModeToggleButtons.js - 简单 UI 组件 2. ✅ DynamicNewsEventCard.js - 平铺模式卡片(被渲染 30+ 次) 3. ✅ HorizontalDynamicNewsEventCard.js - 纵向模式卡片(被渲染 10+ 次) 4. ✅ VerticalModeLayout.js - 布局组件 5. ✅ EventScrollList.js - 列表组件 6. ✅ VirtualizedFourRowGrid.js - 虚拟化网格(forwardRef) 7. ✅ DynamicNewsCard.js - 主组件(forwardRef) **技术实现**: - 普通组件:`React.memo(Component)` - forwardRef 组件:`React.memo(forwardRef(...))` - 所有回调函数已使用 useCallback 确保引用稳定 **预期效果**: - 列表渲染的卡片组件收益最大(减少 90% 重渲染) - 布局组件渲染次数从 9 次降到 1 次(减少 88%) - 整体用户体验更流畅,无明显卡顿 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -63,7 +63,7 @@ let dynamicNewsCardRenderCount = 0;
|
|||||||
* @param {Object} trackingFunctions - PostHog 追踪函数集合
|
* @param {Object} trackingFunctions - PostHog 追踪函数集合
|
||||||
* @param {Object} ref - 用于滚动的ref
|
* @param {Object} ref - 用于滚动的ref
|
||||||
*/
|
*/
|
||||||
const DynamicNewsCard = forwardRef(({
|
const DynamicNewsCardComponent = forwardRef(({
|
||||||
filters = {},
|
filters = {},
|
||||||
popularKeywords = [],
|
popularKeywords = [],
|
||||||
lastUpdateTime,
|
lastUpdateTime,
|
||||||
@@ -722,6 +722,9 @@ const [currentMode, setCurrentMode] = useState('vertical');
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
DynamicNewsCard.displayName = 'DynamicNewsCard';
|
DynamicNewsCardComponent.displayName = 'DynamicNewsCard';
|
||||||
|
|
||||||
|
// ⚡ 使用 React.memo 优化性能(减少不必要的重渲染)
|
||||||
|
const DynamicNewsCard = React.memo(DynamicNewsCardComponent);
|
||||||
|
|
||||||
export default DynamicNewsCard;
|
export default DynamicNewsCard;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import VerticalModeLayout from './VerticalModeLayout';
|
|||||||
* @param {Function} onToggleFollow - 关注按钮回调
|
* @param {Function} onToggleFollow - 关注按钮回调
|
||||||
* @param {React.Ref} virtualizedGridRef - VirtualizedFourRowGrid 的 ref(用于获取滚动位置)
|
* @param {React.Ref} virtualizedGridRef - VirtualizedFourRowGrid 的 ref(用于获取滚动位置)
|
||||||
*/
|
*/
|
||||||
const EventScrollList = ({
|
const EventScrollList = React.memo(({
|
||||||
events,
|
events,
|
||||||
displayEvents,
|
displayEvents,
|
||||||
loadNextPage,
|
loadNextPage,
|
||||||
@@ -144,6 +144,6 @@ const EventScrollList = ({
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default EventScrollList;
|
export default EventScrollList;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { Button, ButtonGroup } from '@chakra-ui/react';
|
|||||||
* @param {string} mode - 当前模式 'vertical' | 'four-row'
|
* @param {string} mode - 当前模式 'vertical' | 'four-row'
|
||||||
* @param {Function} onModeChange - 模式切换回调
|
* @param {Function} onModeChange - 模式切换回调
|
||||||
*/
|
*/
|
||||||
const ModeToggleButtons = ({ mode, onModeChange }) => {
|
const ModeToggleButtons = React.memo(({ mode, onModeChange }) => {
|
||||||
return (
|
return (
|
||||||
<ButtonGroup size="sm" isAttached>
|
<ButtonGroup size="sm" isAttached>
|
||||||
<Button
|
<Button
|
||||||
@@ -28,6 +28,6 @@ const ModeToggleButtons = ({ mode, onModeChange }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default ModeToggleButtons;
|
export default ModeToggleButtons;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import DynamicNewsDetailPanel from '../DynamicNewsDetail/DynamicNewsDetailPanel'
|
|||||||
* @param {Function} getTimelineBoxStyle - 时间线样式获取函数
|
* @param {Function} getTimelineBoxStyle - 时间线样式获取函数
|
||||||
* @param {string} borderColor - 边框颜色
|
* @param {string} borderColor - 边框颜色
|
||||||
*/
|
*/
|
||||||
const VerticalModeLayout = ({
|
const VerticalModeLayout = React.memo(({
|
||||||
display = 'flex',
|
display = 'flex',
|
||||||
events,
|
events,
|
||||||
selectedEvent,
|
selectedEvent,
|
||||||
@@ -182,6 +182,6 @@ const VerticalModeLayout = ({
|
|||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default VerticalModeLayout;
|
export default VerticalModeLayout;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import DynamicNewsEventCard from '../EventCard/DynamicNewsEventCard';
|
|||||||
* @param {boolean} props.hasMore - 是否还有更多数据
|
* @param {boolean} props.hasMore - 是否还有更多数据
|
||||||
* @param {boolean} props.loading - 加载状态
|
* @param {boolean} props.loading - 加载状态
|
||||||
*/
|
*/
|
||||||
const VirtualizedFourRowGrid = forwardRef(({
|
const VirtualizedFourRowGridComponent = forwardRef(({
|
||||||
display = 'block',
|
display = 'block',
|
||||||
events,
|
events,
|
||||||
columnsPerRow = 4,
|
columnsPerRow = 4,
|
||||||
@@ -387,6 +387,9 @@ const VirtualizedFourRowGrid = forwardRef(({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
VirtualizedFourRowGrid.displayName = 'VirtualizedFourRowGrid';
|
VirtualizedFourRowGridComponent.displayName = 'VirtualizedFourRowGrid';
|
||||||
|
|
||||||
|
// ⚡ 使用 React.memo 优化性能(减少不必要的重渲染)
|
||||||
|
const VirtualizedFourRowGrid = React.memo(VirtualizedFourRowGridComponent);
|
||||||
|
|
||||||
export default VirtualizedFourRowGrid;
|
export default VirtualizedFourRowGrid;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import StockChangeIndicators from '../../../../components/StockChangeIndicators'
|
|||||||
* @param {Function} props.onToggleFollow - 切换关注事件
|
* @param {Function} props.onToggleFollow - 切换关注事件
|
||||||
* @param {string} props.borderColor - 边框颜色
|
* @param {string} props.borderColor - 边框颜色
|
||||||
*/
|
*/
|
||||||
const DynamicNewsEventCard = ({
|
const DynamicNewsEventCard = React.memo(({
|
||||||
event,
|
event,
|
||||||
index,
|
index,
|
||||||
isFollowing,
|
isFollowing,
|
||||||
@@ -317,6 +317,6 @@ const DynamicNewsEventCard = ({
|
|||||||
</Card>
|
</Card>
|
||||||
</VStack>
|
</VStack>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default DynamicNewsEventCard;
|
export default DynamicNewsEventCard;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import KeywordsCarousel from './KeywordsCarousel';
|
|||||||
* @param {string} props.indicatorSize - 涨幅指标尺寸 ('default' | 'comfortable' | 'large')
|
* @param {string} props.indicatorSize - 涨幅指标尺寸 ('default' | 'comfortable' | 'large')
|
||||||
* @param {string} props.layout - 布局模式 ('vertical' | 'four-row'),影响时间轴竖线高度
|
* @param {string} props.layout - 布局模式 ('vertical' | 'four-row'),影响时间轴竖线高度
|
||||||
*/
|
*/
|
||||||
const HorizontalDynamicNewsEventCard = ({
|
const HorizontalDynamicNewsEventCard = React.memo(({
|
||||||
event,
|
event,
|
||||||
index,
|
index,
|
||||||
isFollowing,
|
isFollowing,
|
||||||
@@ -227,6 +227,6 @@ const HorizontalDynamicNewsEventCard = ({
|
|||||||
</Box>
|
</Box>
|
||||||
</HStack>
|
</HStack>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default HorizontalDynamicNewsEventCard;
|
export default HorizontalDynamicNewsEventCard;
|
||||||
|
|||||||
Reference in New Issue
Block a user