// src/hooks/useStockSearch.js // 通用股票搜索 Hook - 支持代码、名称、拼音缩写搜索 import { useState, useCallback, useMemo, useEffect, useRef } from 'react'; import debounce from 'lodash/debounce'; import { getApiBase } from '@utils/apiConfig'; /** * 股票搜索 Hook * @param {Object} options 配置项 * @param {number} options.limit 返回结果数量限制,默认 10 * @param {number} options.debounceMs 防抖延迟,默认 300ms * @param {Function} options.onSearch 搜索回调(用于追踪) * @returns {Object} 搜索状态和方法 */ export const useStockSearch = (options = {}) => { const { limit = 10, debounceMs = 300, onSearch } = options; // 使用 ref 存储 onSearch,避免因回调变化导致防抖函数重建 const onSearchRef = useRef(onSearch); useEffect(() => { onSearchRef.current = onSearch; }, [onSearch]); const [searchQuery, setSearchQuery] = useState(''); const [searchResults, setSearchResults] = useState([]); const [isSearching, setIsSearching] = useState(false); const [showResults, setShowResults] = useState(false); // 调用 API 搜索 const searchStocks = useCallback(async (query) => { if (!query || !query.trim()) { setSearchResults([]); setShowResults(false); return; } setIsSearching(true); try { const response = await fetch( `${getApiBase()}/api/stocks/search?q=${encodeURIComponent(query.trim())}&limit=${limit}` ); const data = await response.json(); if (data.success && data.data) { setSearchResults(data.data); setShowResults(true); // 触发搜索回调(用于追踪) onSearchRef.current?.(query, data.data.length); } else { setSearchResults([]); setShowResults(true); onSearchRef.current?.(query, 0); } } catch (error) { console.error('搜索股票失败:', error); setSearchResults([]); } finally { setIsSearching(false); } }, [limit]); // 防抖搜索 const debouncedSearch = useMemo( () => debounce(searchStocks, debounceMs), [searchStocks, debounceMs] ); // 处理搜索输入 const handleSearch = useCallback((value) => { setSearchQuery(value); debouncedSearch(value); }, [debouncedSearch]); // 清空搜索 const clearSearch = useCallback(() => { setSearchQuery(''); setSearchResults([]); setShowResults(false); }, []); // 清理防抖 useEffect(() => { return () => debouncedSearch.cancel?.(); }, [debouncedSearch]); return { // 状态 searchQuery, searchResults, isSearching, showResults, // 方法 handleSearch, clearSearch, setShowResults, }; }; export default useStockSearch;