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

React电影应用:实现动态搜索栏以按需渲染匹配电影卡片

解决方案:实现React电影应用的动态搜索功能

要实现实时搜索匹配电影的功能,我们需要解决两个核心问题:管理搜索输入的状态和基于输入过滤电影数据,同时还要注意不要丢失原始的电影数据(否则清空搜索框时无法恢复全部内容)。下面是具体的修改步骤和完整代码:

第一步:重构App组件,分离原始数据与过滤后数据

首先,我们需要在App组件中维护两个状态:

  • originalMovies:保存从API获取的所有原始电影数据,确保搜索时不会丢失源数据
  • filteredMovies:保存根据搜索关键词过滤后的结果,用于渲染电影卡片

同时添加一个回调函数,让Search组件可以通知App组件更新搜索关键词,进而执行过滤逻辑。

修改后的App组件代码:

import React, { useState, useEffect } from "react";
import "./App.css";
import Logo from "../components/Logo";
import Search from "../components/Search";
import Add_movie_button from "../components/Add_movie_button";
import Random_movie_button from "../components/Random_movie_button";
import Movie_card from "../components/Movie_card";
import axios from "axios";

const BASE_URL = "https://api.themoviedb.org/3/movie/";
const API_KEY = "4bcd155b9b8734cb8559319cdbfaf62f";

function App() {
  // 存储所有原始电影数据
  const [originalMovies, setOriginalMovies] = useState([]);
  // 存储过滤后的电影数据,用于页面渲染
  const [filteredMovies, setFilteredMovies] = useState([]);

  useEffect(() => {
    axios
      .get("http://localhost:5000")
      .then(function (response) {
        const movies = response.data.movies;
        return Promise.all(
          movies.map((movie) =>
            axios.get(
              `${BASE_URL}${movie.movieid}?api_key=${API_KEY}&language=fr`
            )
          )
        );
      })
      .then((responses) => {
        const movieData = responses.map((response) => ({
          Genres: response.data.genres,
          Overview: response.data.overview,
          Poster: response.data.poster_path,
          Company: response.data.production_companies,
          Release: response.data.release_date,
          Title: response.data.title,
          Id: response.data.id,
        }));
        // 初始化时同时设置原始数据和过滤后数据
        setOriginalMovies(movieData);
        setFilteredMovies(movieData);
      });
  }, []);

  // 处理搜索关键词变化的回调函数
  const handleSearchChange = (query) => {
    if (!query.trim()) {
      // 搜索框为空时,显示全部电影
      setFilteredMovies(originalMovies);
      return;
    }
    // 过滤标题以搜索词开头的电影(不区分大小写,提升用户体验)
    const filteredResults = originalMovies.filter(movie => 
      movie.Title.toLowerCase().startsWith(query.toLowerCase())
    );
    setFilteredMovies(filteredResults);
  };

  return (
    <div className="App">
      <div className="Header">
        <Logo />
      </div>
      <div className="Menu">
        {/* 将搜索回调传递给Search组件 */}
        <Search onSearchChange={handleSearchChange} />
        <Add_movie_button />
        <Random_movie_button data={filteredMovies} />
      </div>
      <div className="Movies">
        {/* 使用过滤后的电影数据渲染卡片 */}
        {filteredMovies.map((movie) => (
          <Movie_card key={movie.Id} data={movie} />
        ))}
      </div>
    </div>
  );
}

export default App;

第二步:完善Search组件,管理输入状态并触发搜索

在Search组件中,我们需要使用useState来管理输入框的值,同时在输入变化时调用父组件传递的回调函数,将当前搜索词传递给App组件执行过滤。

修改后的Search组件代码:

import React, { useState } from "react";
import "./style.css";

const Search = ({ onSearchChange }) => {
  // 管理搜索输入框的状态
  const [searchQuery, setSearchQuery] = useState("");

  const handleInputChange = (event) => {
    const inputValue = event.target.value;
    // 更新组件内部的搜索状态
    setSearchQuery(inputValue);
    // 通知父组件执行过滤逻辑
    onSearchChange(inputValue);
  };

  return (
    <div className="Search">
      <input
        type="search"
        id="Search_input"
        placeholder="Rechercher un film ..."
        value={searchQuery}
        onChange={handleInputChange}
      />
    </div>
  );
};

export default Search;

关键细节说明

  1. 为什么分离原始数据与过滤数据?
    如果直接修改原有的movieinfos状态,当用户清空搜索框时,我们无法恢复最初的全部电影数据。分离两个状态可以确保原始数据始终被保留,随时可以复用。

  2. 不区分大小写的搜索
    使用toLowerCase()将电影标题和搜索词统一转换为小写,这样用户输入"har"、"Har"或者"HAR"都能匹配到正确的结果,提升了搜索的友好性。

  3. 更可靠的key值
    将Movie_card的key从movie.Title改为movie.Id,因为电影标题可能存在重复,但ID是唯一的,符合React对key的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 07:27:45