我有一个主页,可以在其中显示搜索结果 searchContext
. 这是我的 home page
代码。
import { useSearch } from "./SearchContext";
const Home = () => {
const { isLoading, search, searchResult } = useSearch();
const startIndex = Math.floor(Math.random() * searchResult.length - 5);
return (
<>
<h3>Home page</h3>
{isLoading ? (
<h1>LOADING...</h1>
) : (
<div>
<div>Search value: {search}</div>
{searchResult.slice(startIndex, startIndex + 5).map((el) => (
<li key={el.id}>{el.title}</li>
))}
</div>
)}
</>
);
};
export default Home;
这是我的 searchContext
.
import { createContext, useEffect, useContext, useState } from "react";
export const SearchContext = createContext({
isLoading: false,
search: "",
searchResult: [],
setSearch: () => {}
});
export const useSearch = () => useContext(SearchContext);
const SearchProvider = ({ children }) => {
const [search, setSearch] = useState("");
const [items, setItems] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const searchNews = async () => {
console.log(search);
setIsLoading(true);
const news = await fetchNews(search, 15, 1);
setItems(news);
setIsLoading(false);
};
const fetchNews = async (section, pageSize, page) => {
// const url = `${baseUrl}${section}?page-size=${pageSize}&page=${page}&api-key=${apiKey}`;
const url = "https://jsonplaceholder.typicode.com/posts";
const news = await fetch(url);
return await news.json();
};
if (search.length > 0) { // I added this condition so that searchNews is not called when search is empty.
searchNews();
} // Here I can add an else statement and call `setItems([])` to set empty array to items but it does not work either.
}, [search]);
return (
<SearchContext.Provider
value={{
isLoading,
search,
searchResult: items,
setSearch: (e) => setSearch(e.target.value)
}}
>
{children}
</SearchContext.Provider>
);
};
export default SearchProvider;
此上下文正在继续调用 searchNews
当我输入文本到 input field
. 这对于搜索和显示结果非常有效。但是当我离开的时候 search string
从…起 input field
然后,我不希望它显示或检索api调用的任何更多结果。现在,如果我慢慢地移除 search string
从…起 input field
. 但是当我离开的时候 search string
越来越快 items
仍然有结果,并在屏幕上显示这些结果 home page
. 我不要这个。我想当 search input
如果是空的,那么我不想显示任何 search result
在…上 home page
或任何页面。
为了解决这个问题,我在中添加了一个if条件 searchContext
检查 search
不是空的,这意味着 input field
不是空的,然后打电话 searchNews
方法并从api加载结果,但如果该结果为空,则不调用 searchNews
不应该显示的内容 search result
在任何页面上。
这是带有搜索输入字段的search.js页面。
import { useSearch } from "./SearchContext";
const Search = () => {
const { setSearch } = useSearch();
return (
<>
<input
type="text"
name="search"
placeholder="Enter search term"
onChange={setSearch}
/>
</>
);
};
export default Search;
当我越来越快地删除搜索字符串时,如何解决此问题?
下面是解决此问题的代码沙盒。
https://codesandbox.io/s/replace-search-current-page-contents-with-search-contents-forked-x4l0o?file=/src/searchcontext.js
2条答案
按热度按时间e5nqia271#
我认为问题在于您正在处理的事件,onchange事件非常适合select元素,而input元素需要oninput事件。尝试使用oninput事件更改onchange事件
6tr1vspr2#
当我们创建任何自动完成组件时,我们需要考虑用户的输入速度,以及每字母搜索是否适合这种情况(很可能不是)。
因此,我们可以学习在等待输入时,在执行提取之前使用debounce或settimeout来创建一个轻微的延迟。
在本例中,创建一个全局变量
timer
它位于组件外部,因此不会在每次渲染时调用/重置它。我们将创建计时器,并在每个输入上使用cleartimeout(计时器)重置计时器。一旦用户暂停键入,您将执行提取。
ps:可以增加100毫秒的延迟以提高性能。我使用的是200ms,它在我的后端运行良好,在不到100ms的时间内返回结果。