使用退格键清除输入字段时显示最后结果的搜索组件
Search component showing last result when input field is cleared using backspace
所以我正在使用 Next.js 并构建了一个基本的搜索页面,其中包含输入并将查询后的结果存储在状态数组上。问题是当我使用退格键快速清除输入字段时,它显示了最后一个关键字的结果。
我认为我以错误的方式使用了 React 状态。
以下是我使用美力搜索查询搜索的方式:
const [search, setSearch] = useState([]);
const [showSearch, setShowSearch] = useState(false);
async function onChange(e) {
if (e.length > 0) {
await client.index('sections')
.search(e)
.then((res) => {
const list = res.hits.map((elm) => ({
title: elm.Title,
content: elm.formattedContent
}));
setSearch(list);
setShowSearch(true);
});
} else {
setSearch([]);
setShowSearch(false);
}
}
这是输入字段和搜索结果:
<div className="searchPage wrapper">
<input
type="text"
aria-label="Search through site content"
placeholder="Search your keywords"
onChange={(e) => onChange(e.target.value);}
/>
{showSearch && (
<div className="searchPageResults">
<p className="suggested">Top Results</p>
{search.length > 0 ? (
<ul>
{search.map((item, index) => (
<li key={`search-${index}`}>
<Link href={`/${item.slug}`}>
<a role="link">
{item.title}
</a>
</Link>
<p>{item.content}</p>
</li>
))}
</ul>
) : (
<p className="noResults">No results found</p>
)}
</div>
)}
</div>
防止这种情况的最佳做法是什么?
您可以在此处查看实时实施:https://budgetbasics.openbudgetsindia.org/search
要重现问题:
- 搜索内容,例如:
Budget
- 显示结果后,按住退格键,清除字段后,显示
b
的搜索结果
- 如果我 select 字段中的所有文本并使用退格键将其删除,问题就不存在了。
问题
我怀疑当你快速退格时,最后一个用“b”发出的请求异步解析在最后一个onChange
调用是在 e.length > 0
为假的地方进行的。 search
状态更新为空数组,一旦最终异步请求解决,search
状态就会更新为“b”的结果。
解决方案
一个可能的解决方案是去除 onChange
处理程序的抖动,这样就不会为快速打字者发出无用的请求。 debounce 来自 lodash 是一个常用的实用程序。我使用了 300ms
的延迟,但这显然是可以调整的,以满足您的需求以及对您或您的一般用户来说最合适的感觉。
import debounce from 'lodash/debounce';
async function onChange(e) {
if (e.length > 0) {
await client.index('sections')
.search(e)
.then((res) => {
const list = res.hits.map((elm) => ({
title: elm.Title,
content: elm.formattedContent
}));
setSearch(list);
setShowSearch(true);
});
} else {
setSearch([]);
setShowSearch(false);
}
}
const debouncedOnChange = useMemo(() => debounce(onChange, 300), []);
...
<input
type="text"
aria-label="Search through site content"
placeholder="Search your keywords"
onChange={(e) => debouncedOnChange(e.target.value)} // <-- use debounced handler
/>
所以我正在使用 Next.js 并构建了一个基本的搜索页面,其中包含输入并将查询后的结果存储在状态数组上。问题是当我使用退格键快速清除输入字段时,它显示了最后一个关键字的结果。
我认为我以错误的方式使用了 React 状态。
以下是我使用美力搜索查询搜索的方式:
const [search, setSearch] = useState([]);
const [showSearch, setShowSearch] = useState(false);
async function onChange(e) {
if (e.length > 0) {
await client.index('sections')
.search(e)
.then((res) => {
const list = res.hits.map((elm) => ({
title: elm.Title,
content: elm.formattedContent
}));
setSearch(list);
setShowSearch(true);
});
} else {
setSearch([]);
setShowSearch(false);
}
}
这是输入字段和搜索结果:
<div className="searchPage wrapper">
<input
type="text"
aria-label="Search through site content"
placeholder="Search your keywords"
onChange={(e) => onChange(e.target.value);}
/>
{showSearch && (
<div className="searchPageResults">
<p className="suggested">Top Results</p>
{search.length > 0 ? (
<ul>
{search.map((item, index) => (
<li key={`search-${index}`}>
<Link href={`/${item.slug}`}>
<a role="link">
{item.title}
</a>
</Link>
<p>{item.content}</p>
</li>
))}
</ul>
) : (
<p className="noResults">No results found</p>
)}
</div>
)}
</div>
防止这种情况的最佳做法是什么?
您可以在此处查看实时实施:https://budgetbasics.openbudgetsindia.org/search
要重现问题:
- 搜索内容,例如:
Budget
- 显示结果后,按住退格键,清除字段后,显示
b
的搜索结果
- 如果我 select 字段中的所有文本并使用退格键将其删除,问题就不存在了。
问题
我怀疑当你快速退格时,最后一个用“b”发出的请求异步解析在最后一个onChange
调用是在 e.length > 0
为假的地方进行的。 search
状态更新为空数组,一旦最终异步请求解决,search
状态就会更新为“b”的结果。
解决方案
一个可能的解决方案是去除 onChange
处理程序的抖动,这样就不会为快速打字者发出无用的请求。 debounce 来自 lodash 是一个常用的实用程序。我使用了 300ms
的延迟,但这显然是可以调整的,以满足您的需求以及对您或您的一般用户来说最合适的感觉。
import debounce from 'lodash/debounce';
async function onChange(e) {
if (e.length > 0) {
await client.index('sections')
.search(e)
.then((res) => {
const list = res.hits.map((elm) => ({
title: elm.Title,
content: elm.formattedContent
}));
setSearch(list);
setShowSearch(true);
});
} else {
setSearch([]);
setShowSearch(false);
}
}
const debouncedOnChange = useMemo(() => debounce(onChange, 300), []);
...
<input
type="text"
aria-label="Search through site content"
placeholder="Search your keywords"
onChange={(e) => debouncedOnChange(e.target.value)} // <-- use debounced handler
/>