如何使用React Hook useEffect实现含searchMovies的搜索栏功能?
基于React useEffect实现电影/演员搜索栏的修正方案与技巧
先修正现有代码的明显错误
1. 状态定义错误修正
你的actorSearch状态类型声明错误,ActorAttributes是单个演员对象,搜索结果应为数组;同时searching状态未定义,建议把search改名为isLoading更语义化:
const Home: React.FC = () => { const [isLoading, setIsLoading] = React.useState(false); const [searchQuery, setSearchQuery] = React.useState(""); // 新增搜索关键词状态 const [movieSearch, setMovieSearch] = React.useState<MovieAttributes[]>([]); const [actorSearch, setActorSearch] = React.useState<ActorAttributes[]>([]); // 修正为数组类型
2. 异步函数错误修正
demo函数里的demoDistrictSearch未定义,推测是笔误应该用movieSearch;同时setSearching需改为setIsLoading,并添加错误处理:
const fetchSearchResults = async (query: string) => { if (!query.trim()) { // 空关键词时清空结果 setMovieSearch([]); setActorSearch([]); return; } setIsLoading(true); try { // 先请求电影 const movieResults = await searchMovies(query); setMovieSearch(movieResults); // 确保电影结果存在时再请求演员 if (movieResults.length > 0) { const actorResults = await searchActors(query, movieResults[0].SID); setActorSearch(actorResults); } } catch (err) { console.error("搜索出错:", err); // 可新增error状态展示错误提示 } finally { setIsLoading(false); } };
3. 正确使用useEffect触发搜索
- 组件挂载时执行一次默认搜索:
React.useEffect(() => { fetchSearchResults("Dumbo"); }, []);
- 根据用户输入实时搜索(带防抖避免频繁请求):
React.useEffect(() => { const timer = setTimeout(() => { fetchSearchResults(searchQuery); }, 300); // 300ms延迟,用户停止输入后再发起请求 return () => clearTimeout(timer); // 清理定时器,避免无效请求 }, [searchQuery]);
4. 添加搜索输入UI
绑定输入框到searchQuery状态,展示搜索结果:
return ( <div> <input type="text" value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} placeholder="搜索电影或演员..." disabled={isLoading} /> {isLoading && <p>搜索中...</p>} <h3>电影结果</h3> <ul> {movieSearch.map(movie => ( <li key={movie.OBJECTID}> <h4>{movie.NAME}</h4> <p>导演: {movie.DIRECTOR}</p> <p>{movie.DESCRIP}</p> </li> ))} </ul> <h3>演员结果</h3> <ul> {actorSearch.map((actor, index) => ( <li key={index}> <p>{actor.NAME} ({actor.TYPE})</p> </li> ))} </ul> </div> );
实用技巧与建议
- 异步请求清理:如果接口支持
AbortController,可在useEffect清理函数中取消请求,避免组件卸载后更新状态导致内存泄漏:React.useEffect(() => { const abortController = new AbortController(); const fetchData = async () => { try { const movieResults = await searchMovies(searchQuery, { signal: abortController.signal }); // 后续逻辑 } catch (err) { if (err instanceof DOMException && err.name === "AbortError") return; console.error(err); } }; fetchData(); return () => abortController.abort(); }, [searchQuery]); - 状态语义化:用
isLoading代替模糊的search命名,让状态用途更清晰。 - 空值防御:使用数组元素前先判断长度,避免
Cannot read property 'SID' of undefined这类错误。 - 错误处理:异步请求必须加
try/catch,可新增error状态展示友好的错误提示。 - 类型严格性:给
searchMovies/searchActors函数添加返回值类型,确保TypeScript类型校验生效,减少运行时错误。
内容的提问来源于stack exchange,提问作者peachy
相关产品推荐
相关产品推荐

