ReactJS实现自适应结果高度的搜索栏UI(含Axios取消令牌)
React 自适应高度搜索栏实现方案
嘿,我来帮你搞定这个自适应高度的搜索栏!结合你已经写好的Axios请求逻辑,咱们可以分几步完美实现需求:
1. 先理清楚核心需求
咱们要做的是:
- 用户输入时触发API搜索,用Axios取消令牌避免重复请求
- 搜索结果容器的高度根据结果数量动态调整:结果少就收缩,结果多(比如10条)就展开到固定高度并支持滚动
2. 完整实现代码&分步说明
我把你的请求逻辑和UI整合在了一起,直接就能用:
import { useState } from 'react'; import axios from 'axios'; function AdaptiveSearchBar() { // 输入框内容状态 const [inputValue, setInputValue] = useState(''); // 搜索结果列表状态 const [searchResults, setSearchResults] = useState([]); // Axios取消令牌相关变量 let CancelToken = axios.CancelToken; let cancelRequest; // 搜索请求函数(基于你的代码优化) const handleSearch = (value) => { // 先取消之前未完成的请求 if (cancelRequest !== undefined) { cancelRequest(); } // 空输入时直接清空结果,避免无效请求 if (!value.trim()) { setSearchResults([]); return; } axios .get( `https://example.com/search`, { cancelToken: new CancelToken(function executor(c) { cancelRequest = c; }), params: { q: value }, } ) .then((response) => { const results = response.data.hits.hits; console.log('搜索结果:', results); setSearchResults(results); }) .catch((error) => { // 取消请求的错误不用抛出,避免控制台干扰 if (!axios.isCancel(error)) { console.error('搜索出错:', error); } }); }; // 计算结果列表的自适应高度 const calculateListHeight = () => { const singleItemHeight = 40; // 假设每条结果固定高度40px,可根据你的UI调整 const maxDisplayItems = 10; // 最多显示10条,超过则滚动 // 取结果数量和最大显示数的最小值,计算容器高度 return `${Math.min(searchResults.length, maxDisplayItems) * singleItemHeight}px`; }; return ( <div style={{ position: 'relative', width: '350px', margin: '2rem auto' }}> {/* 搜索输入框 */} <input type="text" value={inputValue} onChange={(e) => { setInputValue(e.target.value); handleSearch(e.target.value); }} placeholder="输入关键词搜索..." style={{ width: '100%', padding: '10px 15px', border: '1px solid #e0e0e0', borderRadius: '6px', fontSize: '15px', boxSizing: 'border-box' }} /> {/* 自适应高度的结果列表容器 */} {searchResults.length > 0 && ( <div style={{ position: 'absolute', top: 'calc(100% + 8px)', left: 0, right: 0, backgroundColor: '#fff', border: '1px solid #e0e0e0', borderRadius: '6px', boxShadow: '0 4px 12px rgba(0,0,0,0.08)', // 核心:动态计算高度 height: calculateListHeight(), overflowY: searchResults.length > 10 ? 'auto' : 'hidden', zIndex: 100 }} > {searchResults.map((item, index) => ( <div key={item._id} // 用API返回的唯一ID当key,不要用index style={{ padding: '10px 15px', borderBottom: index < searchResults.length - 1 ? '1px solid #f5f5f5' : 'none', cursor: 'pointer', transition: 'background-color 0.2s' }} onClick={() => { // 点击结果的交互:填充到输入框+收起列表 setInputValue(item._source.title); // 替换成你的API返回的显示字段 setSearchResults([]); }} onMouseEnter={(e) => e.target.style.backgroundColor = '#f8f8f8'} onMouseLeave={(e) => e.target.style.backgroundColor = '#fff'} > {item._source.title} {/* 替换成你实际要展示的内容,比如标题/描述 */} </div> ))} </div> )} </div> ); } export default AdaptiveSearchBar;
关键细节解释
- 自适应高度核心:通过
calculateListHeight函数动态计算容器高度,结果少于10条时,容器高度会自动收缩到对应内容高度;10条及以上则固定到最大高度并显示滚动条。如果你的结果项高度不固定,也可以把height设为auto,只设置maxHeight: '400px',这样容器会自动适应内容,超过最大值才滚动。 - 取消令牌优化:新增了空输入判断,避免发送无效请求;同时在catch里过滤掉取消请求的错误,不会在控制台输出冗余信息。
- UI交互优化:给结果项加了 hover 效果,点击结果会填充到输入框并收起列表,提升用户体验;用API返回的唯一ID作为列表项的key,符合React最佳实践。
3. 可选优化建议
- 添加防抖:如果不想用户每输入一个字符就触发请求,可以加个300ms左右的防抖,减少API调用次数:
import { useState, useEffect } from 'react'; // ... 其他代码不变 useEffect(() => { const timer = setTimeout(() => { handleSearch(inputValue); }, 300); // 300ms防抖延迟 return () => clearTimeout(timer); }, [inputValue]); // 输入框的onChange只更新inputValue,不用直接调用handleSearch onChange={(e) => setInputValue(e.target.value)} - 自定义高度规则:如果你的需求不是固定10条,而是比如“超过5条就展开到固定高度”,只需要修改
maxDisplayItems的值即可。
内容的提问来源于stack exchange,提问作者Prabhat kumar
相关产品推荐
相关产品推荐

