You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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>

错误原因分析

  1. 对象调用字符串方法:movieSearch是MovieAttributes类型的对象,不是字符串,直接调用toLowerCase()会报错,必须针对对象中的字符串属性(如NAME、DIRECTOR)进行判断。
  2. 类型定义错误:actorSearch应该是ActorAttributes[]数组类型,但你定义成了单个对象类型,后续渲染演员列表会出问题。
  3. 异步逻辑漏洞:
    • 初始时movieSearch是空数组,直接访问movieSearch[1].SID会触发undefined报错。
    • setSearch(false)放在异步请求外部,会导致搜索状态立刻关闭,用户看不到"Searching..."提示。
  4. 变量名冲突: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:00:52