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

React中点击按钮切换数组中下一部影片的实现方案求助

问题分析与优化方案

现有代码的核心问题

  • 两个独立的useEffect同时发起数据请求,会互相覆盖items状态,导致数据混乱
  • 缺少当前影片索引的状态管理,无法实现“切换到下一部”的逻辑(当前代码直接渲染了所有影片)
  • nextMovie函数未定义,按钮点击无响应
  • 使用v4()作为组件key,每次渲染都会生成新key,引发不必要的组件重渲染
  • 没有数据加载状态和错误处理,用户体验差

优化后的完整代码

import { useState, useEffect } from 'react';
import { v4 as uuidv4 } from 'uuid';

function App() {
  const [items, setItems] = useState([]);
  const [currentIndex, setCurrentIndex] = useState(0);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  // 统一数据源,选择其中一个接口即可
  async function loadMovies() {
    try {
      setIsLoading(true);
      const response = await fetch('https://etbd.tech/nuspljr_334360/sread.php?f=imdb_top_1000.csv');
      if (!response.ok) throw new Error('数据加载失败');
      const data = await response.json();
      setItems(data);
      setError(null);
    } catch (err) {
      setError(err.message);
      setItems([]);
    } finally {
      setIsLoading(false);
    }
  }

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

  // 实现下一部影片切换逻辑,到达末尾后循环回到开头
  const nextMovie = () => {
    if (items.length === 0) return;
    setCurrentIndex(prev => (prev + 1) % items.length);
  };

  const currentMovie = items[currentIndex];

  return (
    <div className="body">
      <h2>Guess that Movie</h2>
      <div className="table">
        {isLoading ? (
          <p>加载中...</p>
        ) : error ? (
          <p className="error">{error}</p>
        ) : currentMovie ? (
          <div key={currentMovie.Series_Title || uuidv4()} className='card'>
            <section className="description">
              <img src={currentMovie.Poster_Link} alt={`${currentMovie.Series_Title} 海报`} />
              <section className="title">
                <p>{currentMovie.Series_Title} ({currentMovie.Released_Year})</p>
                <p>IMDB Rating: {currentMovie.IMDB_Rating}</p>
              </section>
              <p>{currentMovie.Overview}</p>
              <p>{currentMovie.Genre} - {currentMovie.Runtime}</p>
            </section>
          </div>
        ) : (
          <p>暂无影片数据</p>
        )}
        <div className="nav">
          <button 
            className="button" 
            onClick={nextMovie}
            disabled={items.length === 0 || isLoading}
          >
            Next Movie
          </button>
        </div>
      </div>
    </div>
  );
}

export default App;

关键优化点说明

  • 统一数据加载逻辑:合并重复的fetch请求,只保留一个数据源,添加加载状态和错误捕获
  • 新增索引状态:用currentIndex控制当前显示的影片,nextMovie函数通过更新索引实现切换,到达列表末尾后自动循环
  • 优化组件结构:移除不必要的内部组件定义,直接在主组件中渲染当前影片,减少层级复杂度
  • 合理设置组件key:优先使用影片的唯一标识(如Series_Title)作为key,避免不必要的组件重渲染
  • 增强用户体验:添加加载提示、错误提示,按钮在无数据或加载状态下自动禁用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:01:22