// src/views/Community/hooks/useEventData.js // 事件数据加载逻辑 Hook import { useState, useEffect, useRef, useCallback } from 'react'; import { debounce } from 'lodash'; import { eventService } from '../../../services/eventService'; import { logger } from '../../../utils/logger'; /** * 事件数据加载 Hook * @param {Object} filters - 筛选条件 * @param {number} pageSize - 每页数量 * @returns {Object} 事件数据和加载状态 */ export const useEventData = (filters, pageSize = 10) => { const [events, setEvents] = useState([]); const [pagination, setPagination] = useState({ current: 1, pageSize: pageSize, total: 0 }); const [loading, setLoading] = useState(false); const [lastUpdateTime, setLastUpdateTime] = useState(new Date()); // 加载事件列表 // ✅ 修复闭包陷阱: 接受 currentFilters 参数,避免使用闭包中的旧 filters const loadEvents = useCallback(async (page = 1, currentFilters = null) => { // 使用传入的 currentFilters 或回退到闭包中的 filters const filtersToUse = currentFilters || filters; const requestParams = { ...filtersToUse, page, per_page: pagination.pageSize }; logger.debug('useEventData', '📡 【准备发起API请求】loadEvents 被调用', { page, currentFilters, filtersToUse, requestParams }); setLoading(true); try { logger.debug('useEventData', '🌐 正在调用 eventService.getEvents', { requestParams }); const response = await eventService.getEvents(requestParams); logger.debug('useEventData', '✅ API响应成功', { success: response.success, eventCount: response.data?.events?.length, total: response.data?.pagination?.total }); if (response.success && response.data) { const events = response.data.events || []; const paginationData = response.data.pagination || {}; setEvents(events); setPagination({ current: paginationData.page || page, pageSize: paginationData.per_page || pagination.pageSize, total: paginationData.total || 0 }); setLastUpdateTime(new Date()); logger.debug('useEventData', 'loadEvents 成功', { count: events.length, total: paginationData.total || 0 }); } } catch (error) { logger.error('useEventData', '❌ loadEvents 失败', error, { page, filtersToUse }); } finally { setLoading(false); } }, [filters, pagination.pageSize]); // 创建防抖的 loadEvents 函数(500ms 防抖延迟) // ✅ 修复闭包陷阱: 防抖函数接受 filters 参数并传递给 loadEvents const debouncedLoadEvents = useRef( debounce((page, filters) => { logger.debug('useEventData', '⏱️ 【防抖延迟500ms结束】即将执行 loadEvents', { page, filters }); loadEvents(page, filters); }, 500) ).current; // 监听 filters 变化,自动加载数据 // 防抖优化:用户快速切换筛选条件时,只执行最后一次请求 useEffect(() => { logger.debug('useEventData', '🔔 【filters变化触发useEffect】完整filters对象:', filters); logger.debug('useEventData', '详细参数:', { page: filters.page || 1, sort: filters.sort, importance: filters.importance, date_range: filters.date_range, q: filters.q, industry_code: filters.industry_code, timestamp: new Date().toISOString() }); // ✅ 使用防抖加载事件,将当前 filters 传递给防抖函数 logger.debug('useEventData', '⏰ 启动防抖计时器(500ms),传递最新filters'); debouncedLoadEvents(filters.page || 1, filters); // 组件卸载时取消防抖 return () => { debouncedLoadEvents.cancel(); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [filters]); // 监听 filters 状态变化 return { events, pagination, loading, lastUpdateTime, loadEvents }; };