如何使用React TypeScript展示搜索结果具体属性并修复代码错误?
问题:如何展示电影/演员搜索结果的具体属性?
现有代码
接口定义
export interface ActorAttributes { TYPE?: string, NAME?: string, } export interface MovieAttributes { OBJECTID: number, SID: string, NAME: string, DIRECTOR: string, DESCRIP: string, }
App.tsx 代码
import { useEffect, useState } from 'react'; import { searchMovies, searchActors, MovieAttributes, ActorAttributes } from "@utils/atts" const Home: React.FC = () => { const [search, setSearch] = useState(false); const [movieSearch, setMovieSearch] = useState<MovieAttributes[]>([]); const [actorSearch, setActorSearch] = useState<ActorAttributes>([]); const [searchTerm, setSearchTerm] = useState(''); useEffect(() => { if (searchTerm.length > 0) { setSearch(true); searchMovies(searchTerm).then(results => { setMovieSearch(results); }); searchActors(searchTerm, movieSearch[1].SID).then(results => { setActorSearch(results); }); setSearch(false); } }, [searchTerm, movieSearch]); const handleSearchTermChange = (event: React.ChangeEvent<HTMLInputElement>) => { setSearchTerm(event.target.value); } return ( <div> <input type="text" value={searchTerm} onChange={handleSearchTermChange} /> {search && <p>Searching...</p>} {movieSearch.length > 0 && <p>Found {movieSearch.length} movies</p>} {actorSearch.length > 0 && <p>Found {actorSearch.length} actors</p>} </div> ); }
当前问题
已实现搜索结果数量展示,但不知道如何渲染电影/演员的具体属性(如NAME、DIRECTOR等)。尝试编写渲染代码时,出现错误:movieAttributes不存在toLowerCase()方法,不确定思路是否正确,寻求解决方案。
尝试的错误代码
<div className="App"> <ul className="posts"> <input type="text" onChange={handleSearchTermChange} /> {movieSearch.map((movieSearch) => { if (searchTerm == "" || movieSearch.toLowerCase().includes(searchTerm.toLowerCase())) { return ( <li key={movieSearch.OBJECTID}> <h3>{movieSearch.NAME}</h3> <p>{movieSearch.DIRECTOR}</p> <p>{movieSearch.DESCRIP}</p> </li> ); } return null; )} </ul> </div>
错误原因分析
- 对象调用字符串方法:
movieSearch是MovieAttributes类型的对象,不是字符串,直接调用toLowerCase()会报错,必须针对对象中的字符串属性(如NAME、DIRECTOR)进行判断。 - 类型定义错误:
actorSearch应该是ActorAttributes[]数组类型,但你定义成了单个对象类型,后续渲染演员列表会出问题。 - 异步逻辑漏洞:
- 初始时
movieSearch是空数组,直接访问movieSearch[1].SID会触发undefined报错。 setSearch(false)放在异步请求外部,会导致搜索状态立刻关闭,用户看不到"Searching..."提示。
- 初始时
- 变量名冲突:
map的参数用了和状态变量同名的movieSearch,容易混淆,建议改成movieItem。
解决方案
1. 修正类型定义
将actorSearch的类型改为数组:
const [actorSearch, setActorSearch] = useState<ActorAttributes[]>([]);
2. 修复useEffect异步逻辑
确保请求完成后再更新状态,同时处理空数组的边界情况:
useEffect(() => { if (searchTerm.length === 0) { setMovieSearch([]); setActorSearch([]); return; } setSearch(true); // 先搜索电影,再用有效电影的SID搜索演员 searchMovies(searchTerm) .then(movieResults => { setMovieSearch(movieResults); if (movieResults.length > 0) { return searchActors(searchTerm, movieResults[0].SID); } return []; }) .then(actorResults => { setActorSearch(actorResults); }) .catch(err => { console.error('搜索出错:', err); }) .finally(() => { setSearch(false); }); }, [searchTerm]);
3. 正确渲染电影/演员列表(含搜索过滤)
针对对象的具体属性做过滤判断,同时渲染完整信息:
return ( <div className="App"> <input type="text" value={searchTerm} onChange={handleSearchTermChange} placeholder="搜索电影或演员..." /> {search && <p>搜索中...</p>} {/* 渲染电影列表 */} {movieSearch.length > 0 && ( <> <p>找到 {movieSearch.length} 部电影</p> <ul className="posts"> {movieSearch.map(movieItem => { const matches = searchTerm === "" || movieItem.NAME.toLowerCase().includes(searchTerm.toLowerCase()) || movieItem.DIRECTOR.toLowerCase().includes(searchTerm.toLowerCase()); if (matches) { return ( <li key={movieItem.OBJECTID}> <h3>{movieItem.NAME}</h3> <p>导演:{movieItem.DIRECTOR}</p> <p>简介:{movieItem.DESCRIP}</p> </li> ); } return null; })} </ul> </> )} {/* 渲染演员列表 */} {actorSearch.length > 0 && ( <> <p>找到 {actorSearch.length} 位演员</p> <ul className="actors"> {actorSearch.map((actorItem, index) => ( <li key={index}> <p>姓名:{actorItem.NAME || '未知'}</p> <p>类型:{actorItem.TYPE || '未知'}</p> </li> ))} </ul> </> )} </div> );
4. 额外优化建议
- 如果后端能给演员返回唯一ID,替换掉当前用的
index作为key,提升性能。 - 可以给搜索框添加防抖,避免输入时频繁触发请求。
- 增加无结果提示,当搜索后没有匹配内容时告知用户。
内容的提问来源于stack exchange,提问作者peachy
相关产品推荐
相关产品推荐

