OMDB API返回undefined搜索结果及CSS样式不生效问题求助
问题:电影网站集成OMDB API后搜索返回undefined,自定义CSS未生效
我正在开发一个模拟电影网站,集成OMDB API后搜索电影只显示undefined,同时自定义CSS样式也没生效,相关代码如下:
原Home组件代码
import React, { useEffect, useState } from "react"; import Nav from "../ui/Nav"; import axios from "axios"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons"; import { useNavigate } from "react-router-dom"; const API_URL = "http://www.omdbapi.com/?apikey=cca6a59"; function Home() { const [searchItem, setSearchItem] = useState(""); const [movies, setMovies] = useState([]); const navigate = useNavigate() function onSearch() { // console.log("search term", searchItem); setTimeout(() => { fetchMovies(searchItem); navigate(`/movies/${searchItem}`) }) fetchMovies(searchItem); } async function fetchMovies(title) { const { data } = await axios.get(`${API_URL}&s=${title}`); setMovies(data); } useEffect(() => { fetchMovies(""); }, []); return ( <> <Nav /> <section id="landing"> <div className="landing__container"> <div className="landing__row"> <h1 className="landing__header"> America's favorite online movie search engine! </h1> <h3 className="landing__sub-header"> Find your favorite movie here. </h3> <div className="search__container"> <input type="text" value={searchItem} className="search__bar" placeholder="Search Movie Title" onChange={(event) => { setSearchItem(event.target.value); }} /> <button onClick={() => onSearch(movies)} className="input__btn"> <FontAwesomeIcon icon={faMagnifyingGlass} /> </button> </div> </div> </div> </section> </> ); } export default Home;
原Movies组件代码
import axios from "axios"; import React, { useEffect, useState } from "react"; import Nav from "../ui/Nav"; const API_URL = "http://www.omdbapi.com/?apikey=cca6a59"; function Movies() { const [movies, setMovies] = useState([]); async function fetchMovies(title) { const { data } = await axios.get(`${API_URL}&s=${title}`); setMovies(data.Search); } useEffect(() => { fetchMovies(); }, []); return ( <> <Nav /> <div className="movie__row"> <div className="movie__wrapper"> {movies.map((movie) => ( <div className="movie"> <div className="movie__img" key={movie.id}> <img src={`${movie.Poster}`} alt="poster" /> <div className="movies__content"> <h1>{movie.Title}</h1> <h1>{movie.Year}</h1> <p onClick={`${movie.imdbID}`}>SEE MORE</p> </div> </div> </div> ))} </div> </div> </> ); } export default Movies;
问题修复方案
一、搜索返回undefined的解决步骤
Movies组件获取路由搜索关键词
从路由参数中提取用户搜索的电影名,需要引入useParams:import { useParams, useNavigate } from "react-router-dom";组件内获取参数并修改数据请求逻辑:
const { title } = useParams(); useEffect(() => { fetchMovies(title); }, [title]); // 路由参数变化时自动重新请求数据处理API空结果或异常
OMDB API无搜索结果时不会返回data.Search,直接访问会导致undefined,需添加判断逻辑:async function fetchMovies(searchTitle) { if (!searchTitle.trim()) return; try { const { data } = await axios.get(`${API_URL}&s=${searchTitle}`); setMovies(data.Search || []); // 无结果时设为空数组避免报错 } catch (err) { console.error("获取电影数据失败:", err); setMovies([]); } }简化Home组件搜索逻辑
原代码重复调用fetchMovies且无意义使用setTimeout,直接改为路由跳转即可:function onSearch() { if (searchItem.trim()) { navigate(`/movies/${searchItem}`); } }额外给搜索框添加回车触发搜索的功能:
<input // 保留原有属性 onKeyDown={(e) => e.key === 'Enter' && onSearch()} />修正循环key值与点击事件
- key需绑定在循环的最外层元素上,OMDB返回的电影唯一标识是
imdbID而非movie.id - "SEE MORE"点击事件需写成函数才能实现跳转:
{movies.map((movie) => ( <div className="movie" key={movie.imdbID}> <div className="movie__img"> <img src={movie.Poster !== "N/A" ? movie.Poster : "https://via.placeholder.com/300x450?text=No+Poster"} alt={movie.Title} /> <div className="movies__content"> <h1>{movie.Title}</h1> <h1>{movie.Year}</h1> <p onClick={() => navigate(`/movie/${movie.imdbID}`)}>SEE MORE</p> </div> </div> </div> ))}- key需绑定在循环的最外层元素上,OMDB返回的电影唯一标识是
二、自定义CSS未生效的排查方向
- 检查CSS文件是否正确导入到对应组件中,比如Home和Movies组件是否引入了样式文件
- 核对CSS选择器与组件内
className的拼写是否一致,比如movies__content这类类名有没有写错 - 排查样式优先级问题,若框架默认样式覆盖了自定义样式,可尝试使用更具体的选择器测试
- 确认CSS文件的相对路径是否正确,是否放置在项目的正确目录下
修改后的完整代码
Home组件
import React, { useState } from "react"; import Nav from "../ui/Nav"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons"; import { useNavigate } from "react-router-dom"; const API_URL = "http://www.omdbapi.com/?apikey=cca6a59"; function Home() { const [searchItem, setSearchItem] = useState(""); const navigate = useNavigate(); function onSearch() { if (searchItem.trim()) { navigate(`/movies/${searchItem}`); } } return ( <> <Nav /> <section id="landing"> <div className="landing__container"> <div className="landing__row"> <h1 className="landing__header"> America's favorite online movie search engine! </h1> <h3 className="landing__sub-header"> Find your favorite movie here. </h3> <div className="search__container"> <input type="text" value={searchItem} className="search__bar" placeholder="Search Movie Title" onChange={(event) => { setSearchItem(event.target.value); }} onKeyDown={(e) => e.key === 'Enter' && onSearch()} /> <button onClick={onSearch} className="input__btn"> <FontAwesomeIcon icon={faMagnifyingGlass} /> </button> </div> </div> </div> </section> </> ); } export default Home;
Movies组件
import axios from "axios"; import React, { useEffect, useState } from "react"; import Nav from "../ui/Nav"; import { useParams, useNavigate } from "react-router-dom"; const API_URL = "http://www.omdbapi.com/?apikey=cca6a59"; function Movies() { const [movies, setMovies] = useState([]); const { title } = useParams(); const navigate = useNavigate(); async function fetchMovies(searchTitle) { if (!searchTitle.trim()) return; try { const { data } = await axios.get(`${API_URL}&s=${searchTitle}`); setMovies(data.Search || []); } catch (err) { console.error("获取电影数据失败:", err); setMovies([]); } } useEffect(() => { fetchMovies(title); }, [title]); return ( <> <Nav /> <div className="movie__row"> <div className="movie__wrapper"> {movies.length === 0 ? ( <p>没有找到相关电影,请尝试其他关键词</p> ) : ( movies.map((movie) => ( <div className="movie" key={movie.imdbID}> <div className="movie__img"> <img src={movie.Poster !== "N/A" ? movie.Poster : "https://via.placeholder.com/300x450?text=No+Poster"} alt={movie.Title} /> <div className="movies__content"> <h1>{movie.Title}</h1> <h1>{movie.Year}</h1> <p onClick={() => navigate(`/movie/${movie.imdbID}`)}>SEE MORE</p> </div> </div> </div> )) )} </div> </div> </> ); } export default Movies;
内容的提问来源于stack exchange,提问作者Cam Watkins
相关产品推荐
相关产品推荐

