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

React组件复用:电影应用的数据获取与跨组件排序问题

React电影应用问题解决方案

问题背景

开发ReactJS电影展示应用,已实现从API加载数据并通过MovieList组件展示,但存在两个问题:

  1. fetchMovies函数仅在App组件内部定义,无法被其他组件调用;
  2. 当前排序函数无法正常工作,且仅App组件能触发排序,其他组件无法执行排序操作。

问题1:让其他组件能调用fetchMovies函数

解决方案:通过Props传递或Context共享

如果调用组件是App的直接子组件,直接通过props传递函数即可;若组件层级较深,推荐用React Context全局共享该函数。

方案1:Props传递(适合层级浅的场景)

  1. 新增触发刷新的子组件:
function RefreshButton(props) {
  return <button onClick={props.onRefresh}>重新加载电影</button>;
}
  1. 修改App组件,传递fetchMovies:
function App() {
  const [movies, setMovies] = useState([]);

  useEffect(() => {
    fetchMovies();
  }, []);

  const fetchMovies = async () => {
    let response = await fetch('SOMEURLTOMOVIES');
    let result = await response.json();
    setMovies(result.Search);
  };

  // 排序逻辑后续修复
  const handleSort = () => {};

  return (
    <div className="App">
      <button onClick={handleSort}>排序</button>
      <RefreshButton onRefresh={fetchMovies} />
      <MovieList movies={movies} />
    </div>
  );
}

export default App;

方案2:React Context(适合层级深的场景)

  1. 创建Context封装数据与操作:
// MovieContext.js
import { createContext, useContext, useState } from 'react';

const MovieContext = createContext();

export function MovieProvider({ children }) {
  const [movies, setMovies] = useState([]);

  const fetchMovies = async () => {
    let response = await fetch('SOMEURLTOMOVIES');
    let result = await response.json();
    setMovies(result.Search);
  };

  return (
    <MovieContext.Provider value={{ movies, fetchMovies }}>
      {children}
    </MovieContext.Provider>
  );
}

export function useMovieContext() {
  return useContext(MovieContext);
}
  1. 在App中使用Provider,其他组件通过Hook获取函数:
// App.js
import { MovieProvider } from './MovieContext';

function App() {
  return (
    <MovieProvider>
      <div className="App">
        <RefreshButton />
        <MovieList />
      </div>
    </MovieProvider>
  );
}

// RefreshButton.js
import { useMovieContext } from './MovieContext';

function RefreshButton() {
  const { fetchMovies } = useMovieContext();
  return <button onClick={fetchMovies}>重新加载电影</button>;
}

问题2:修复排序函数并让其他组件可触发排序

问题分析

当前排序逻辑的两个核心错误:

  • 字符串类型的Title不能用减号-比较,需用localeCompare方法;
  • Array.sort()会直接修改原数组,违反React状态不可直接修改的原则,需先创建数组副本;
  • 缺少升降序切换逻辑,需维护排序方向状态。

解决方案

  1. 维护排序方向状态,修复排序逻辑;
  2. 将排序触发函数通过props传递给需要的组件。

代码示例

修改后的App组件:

function App() {
  const [movies, setMovies] = useState([]);
  // 新增排序方向状态,默认升序
  const [isAscending, setIsAscending] = useState(true);

  useEffect(() => {
    fetchMovies();
  }, []);

  const fetchMovies = async () => {
    let response = await fetch('SOMEURLTOMOVIES');
    let result = await response.json();
    setMovies(result.Search);
  };

  const handleSort = () => {
    // 创建数组副本,避免修改原状态
    const sortedMovies = [...movies].sort((a, b) => {
      // 用localeCompare正确比较字符串
      const compareResult = a.Title.localeCompare(b.Title);
      // 根据排序方向决定正序/倒序
      return isAscending ? compareResult : -compareResult;
    });
    setMovies(sortedMovies);
    // 切换排序方向
    setIsAscending(!isAscending);
  };

  return (
    <div className="App">
      <button onClick={handleSort}>
        {isAscending ? '降序排序' : '升序排序'}
      </button>
      {/* 将排序函数传递给MovieList */}
      <MovieList movies={movies} onSort={handleSort} />
    </div>
  );
}

export default App;

修改后的MovieList组件(支持内部触发排序):

function MovieList(props) {
  const movieItems = props.movies.map((movie) => {
    return <li key={movie.imdbID}>{movie.Title}</li>;
  });

  return (
    <div>
      {/* 组件内部的排序按钮 */}
      <button onClick={props.onSort}>列表内排序</button>
      <ul>{movieItems}</ul>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 00:55:15