Files
vf_react/src/hooks/useStockSearch.js

101 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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;