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

React JS中如何按条件调用两个API实现默认热门展示与搜索查询功能

问题修复方案


核心错误点

  • API调用逻辑写反:现有代码有搜索关键词时请求热门接口,无搜索词时请求搜索接口,与需求完全相反
  • 过滤函数逻辑颠倒:有搜索词时未做匹配直接返回所有数据,无搜索词时反而执行关键词匹配,逻辑完全错误
  • 无结果判断逻辑错误:仅判断原始接口返回数组长度,过滤后的数组为空时不会触发提示,导致出现空白页面
  • 搜索接口使用HTTP协议:会被浏览器混合内容安全策略拦截,导致请求失败无返回
  • 缺失字段兜底:热门列表可能包含剧集类内容,无original_title字段,会出现空标题卡片

修正后完整代码

import React ,{useEffect, useState} from 'react';
import {Grid, Button, Card, CardActionArea, CardActions, CardContent, CardMedia, Typography, makeStyles } from '@material-ui/core';
import Rating from '@material-ui/lab/Rating';
import Watchlist from '../Products/Watchlist.jsx';
import Error from '../Error/Error.jsx';


const useStyles = makeStyles (theme => ({
    cardButton:{
        '&:hover':{
           backgroundColor:'#356E44',
           color: 'white',
        }
    },
Main:{
    width: "100vw",
    justifyContent: " flex-start",
    display: "flex",
    flexWrap: "wrap",
    alignItems: "stretch", 
    alignContent: " flex-start",
    columnGap: "20px",
    rowGap:"5px",
},
cardMain:{
    width: 'min-content',
    height: 'min-content',
    margin: '10px',
    '&:hover':{
        boxShadow: '5px 3px 5px white',
     }
},

cardImage:{
    height: '150px',
    marginLeft: '7px',
    marginRight: '7px',
    marginTop: '5px',
    objectFit: 'cover',
},
cardContent: {
    width: '250px',
    height: '50px',
    wordBreak: 'break-word',
    fontSize: '1rem',
    fontWeight: 'bolder',
},
typography1:{
    float: 'right',
   
},
typography2:{
    float: 'left',
},
}));


const Products = (props) =>{
    

const classes = useStyles();

const [movieData, setMovieData] = useState([]);
 
const [watchlist, setWatchlist] = useState ([]);

// 修正过滤逻辑
const filterData = (val) => {
     const keyword = props.searchText?.trim().toLowerCase() || '';
     // 无搜索词直接返回所有数据
     if (!keyword) return true;
     // 有搜索词时做匹配,增加字段兜底
     const title = (val.original_title || val.original_name || '').toLowerCase();
     return title.includes(keyword);
  };


useEffect (()=> {
    const getMovieList  = async () => {
        const TrendingUrl = 'https://api.themoviedb.org/3/trending/all/day?api_key=API_keyID' ;
        // 修正为HTTPS协议,关键词做编码处理
        const allResultsUrl = `https://api.themoviedb.org/3/search/movie?api_key=API_keyID&query=${encodeURIComponent(props.searchText)}`;
        // 修正API调用逻辑:有搜索词调用搜索接口,无则调用热门接口
        const targetUrl = props.searchText?.trim() ? allResultsUrl : TrendingUrl;
        const response = await fetch(targetUrl);
                try {
                    const responseJson = await response.json();
                    const data = responseJson.results || [];
                    setMovieData(data);
                } catch (err) {
                    console.error(err);
                    setMovieData([]);
                }
        
    };
    getMovieList();
 }, [props.searchText]);


 const handleWatchlist = (movieItem) => {
     const newWatchlist = [...watchlist , movieItem];
     setWatchlist (newWatchlist);
 }

// 先拿到过滤后的数据再做判断
const filteredList = movieData.filter(filterData);

return (
    <> 
        <Grid
        item
        xs
        container
        direction="column"
        justifyContent="flex-start"
        alignItems="flex-start"
        style={{ backgroundColor: "black", width: "100%", height: "100%"}}
        >
            <div  className ={classes.Main} > 
                {/* 判断过滤后的数组长度,而非原数组 */}
                { filteredList.length === 0 ? (
                    <h1 style = {{color: 'red', fontSize : "2rem"}}>No search results found</h1>
                ) : filteredList.map((movie) =>{
                    return(
                    <Card className={classes.cardMain}  key={movie.id}>
                        <CardActionArea>
                            <CardMedia className = {classes.cardImage}>
                                <img style = {{width: '100%', height: '100%', objectFit: 'cover'}} 
                                    src ={movie.poster_path ? `https://image.tmdb.org/t/p/original${movie.poster_path}` : 'https://via.placeholder.com/250x150?text=No+Image'} 
                                    alt = "movie poster"/>
                            </CardMedia>
                            <CardContent className = {classes.cardContent}>
                                <Typography>  {movie.original_title || movie.original_name || '无标题'} </Typography>
                                <Typography 
                                            className = {classes.typography1} 
                                            variant="body2" 
                                            component = "p"
                                    > {movie.release_date || movie.first_air_date || '暂无日期'} 
                                    </Typography>
                                <Rating 
                                        className = {classes.typography2} 
                                        name = "ratings"
                                        value =  {movie.vote_average ? movie.vote_average/2 : 0} 
                                        precision={0.5}
                                        readOnly                                
                                />  
                                
                            </CardContent>
                        </CardActionArea>
                        <CardActions style = {{justifyContent: 'space-evenly'}} >
                            <Button className = {classes.cardButton} size = "small">Watch</Button>
                            <Button className = {classes.cardButton} size = "small" >Share</Button>
                            <Button className = {classes.cardButton} size = "small" onClick = { () => handleWatchlist(movie) }> Add </Button> 
                        </CardActions>
                    </Card>
                    );
                })}
            </div>
        </Grid>
    </>
)
};

export default Products;

可选优化点

  • 增加请求loading状态,请求过程中展示加载提示,提升用户体验
  • 增加防抖逻辑,避免搜索输入过程中频繁触发接口请求

内容的提问来源于stack exchange,提问作者Tapesh Patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 09:24:02