/** * 游戏分类菜单组件 * * 展示游戏分类,支持切换,使用真实数据 */ import React, { useRef, useEffect, useState, useCallback, useMemo } from 'react'; import { View, Text, ScrollView, TouchableOpacity, Animated } from 'react-native'; // import type { GameCategory } from '@/types/home'; import { styles } from './styles'; import { useGameMainMenus, useMenuDataLoaded } from '@/hooks/useGameMenus'; // import useGameStore from '@/stores/gameStore'; import { ThemeEnum } from '@/constants/theme'; interface GameMainMenuProps { theme: ThemeEnum; selectedCategory?: string; onCategorySelect?: (categoryId: string) => void; topHeight?: number; showSubMenus?: boolean; } /** * 游戏分类菜单组件 */ export default function GameMainMenu({ theme, selectedCategory = '103', onCategorySelect, topHeight = 0, showSubMenus = true, }: GameMainMenuProps) { const s = styles[theme]; const scrollViewRef = useRef(null); const gameMenus = useGameMainMenus(theme); // 检查数据加载完成 const isDataLoaded = useMenuDataLoaded(); // 使用 useMemo 缓存找到的索引,避免每次都重新计算 const selectedIndex = useMemo(() => { return gameMenus.findIndex((cat) => cat.key === selectedCategory); }, [selectedCategory, gameMenus]); // 当分类改变时,滚动到该分类 useEffect(() => { if (selectedIndex >= 0) { scrollViewRef.current?.scrollTo({ x: selectedIndex * 100, animated: true, }); } }, [selectedIndex]); // 使用 useCallback 稳定 onPress 回调 const handleCategoryPress = useCallback((categoryKey: string) => { onCategorySelect?.(categoryKey); }, [onCategorySelect]); // 骨架屏 - 显示加载中的占位符 const renderSkeleton = () => ( {[1, 2, 3, 4, 5].map((index) => ( ))} ); // 如果动态数据还未加载,显示骨架屏 if (!isDataLoaded) { return renderSkeleton(); } return ( {gameMenus.map((menu) => ( handleCategoryPress(menu.key)} activeOpacity={0.7} > {menu.icon || '🎮'} {menu.name} ))} ); }