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

React电影列表日期降序排序与评分单次增减问题求助

电影列表功能修复与扩展

一、实现点击date表头按日期降序排序

  • 在组件state中新增排序状态,记录当前排序字段和顺序:
    this.state = {
      movies: [/* 原电影数据 */],
      sortKey: 'rating', // 默认按rating排序
      sortOrder: 'asc' // 默认升序
    }
    
  • 移除constructor中直接修改state的排序代码,改为调用统一的排序函数初始化
  • 编写通用排序函数,支持切换排序字段和顺序:
    handleSort = (key) => {
      // 点击当前排序字段则切换顺序,点击date默认降序,点击其他字段默认升序
      const newOrder = this.state.sortKey === key ? 
        (this.state.sortOrder === 'asc' ? 'desc' : 'asc') : 
        (key === 'date' ? 'desc' : 'asc');
      // 复制数组避免修改原state数据
      const sortedMovies = [...this.state.movies].sort((a, b) => {
        if (key === 'date') {
          return newOrder === 'desc' ? b.date - a.date : a.date - b.date;
        } else if (key === 'rating') {
          return newOrder === 'asc' ? a.rating - b.rating : b.rating - a.rating;
        }
        return 0;
      });
      this.setState({
        movies: sortedMovies,
        sortKey: key,
        sortOrder: newOrder
      });
    }
    
  • 修改表头渲染逻辑,给所有表头绑定点击事件,并添加排序箭头标识:
    Object.keys(this.state.movies[0]).map((elem, ind) => {
      return (
        <th 
          key={ind} 
          onClick={() => this.handleSort(elem)}
          style={{cursor: 'pointer'}}
        >
          {elem}
          {this.state.sortKey === elem && (this.state.sortOrder === 'desc' ? ' ↓' : ' ↑')}
        </th>
      )
    })
    

二、修复评分按钮无限触发问题

问题根源是直接修改了state中的原对象,导致React状态更新异常。必须通过创建新数组/对象的方式更新状态:

  • 修改increment函数:
    increment = (movie) => {
      const updatedMovies = this.state.movies.map(m => {
        if (m.id === movie.id) {
          // 复制原对象并修改rating,不直接修改原数据
          return {...m, rating: m.rating + 1};
        }
        return m;
      });
      this.setState({movies: updatedMovies});
    }
    
  • 修改decrement函数:
    decrement = (movie) => {
      const updatedMovies = this.state.movies.map(m => {
        if (m.id === movie.id) {
          return {...m, rating: m.rating - 1};
        }
        return m;
      });
      this.setState({movies: updatedMovies});
    }
    
  • 修改remove函数:
    remove = (index) => {
      // 通过slice生成新数组,替代splice修改原数组
      const updatedMovies = [...this.state.movies.slice(0, index), ...this.state.movies.slice(index + 1)];
      this.setState({movies: updatedMovies});
    }
    
  • 将所有类方法改为箭头函数,避免手动绑定this的繁琐操作

完整修改后的代码

import React from "react";

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      movies: [
        { id: 1, name: "Deadpool", date: 2016, time: 108, genre: 'action', rating: 5 },
        { id: 2, name: "The Avengers", date: 2012, time: 143, genre: 'action', rating: 4 },
        { id: 3, name: "Slayers", date: 2022, time: 88, genre: 'fantasy,comedy', rating: 3 },
      ],
      sortKey: 'rating',
      sortOrder: 'asc'
    }
    // 初始化按rating升序排序
    this.handleSort('rating');
  }

  handleSort = (key) => {
    const newOrder = this.state.sortKey === key ? 
      (this.state.sortOrder === 'asc' ? 'desc' : 'asc') : 
      (key === 'date' ? 'desc' : 'asc');
    const sortedMovies = [...this.state.movies].sort((a, b) => {
      if (key === 'date') {
        return newOrder === 'desc' ? b.date - a.date : a.date - b.date;
      } else if (key === 'rating') {
        return newOrder === 'asc' ? a.rating - b.rating : b.rating - a.rating;
      }
      return 0;
    });
    this.setState({
      movies: sortedMovies,
      sortKey: key,
      sortOrder: newOrder
    });
  }

  star(i) {
    let arr = new Array(i);
    return arr.fill("*");
  }

  remove = (index) => {
    const updatedMovies = [...this.state.movies.slice(0, index), ...this.state.movies.slice(index + 1)];
    this.setState({movies: updatedMovies});
  }

  increment = (movie) => {
    const updatedMovies = this.state.movies.map(m => {
      if (m.id === movie.id) {
        return {...m, rating: m.rating + 1};
      }
      return m;
    });
    this.setState({movies: updatedMovies});
  }

  decrement = (movie) => {
    const updatedMovies = this.state.movies.map(m => {
      if (m.id === movie.id) {
        return {...m, rating: m.rating - 1};
      }
      return m;
    });
    this.setState({movies: updatedMovies});
  }

  render() {
    return <>
      <h1>Cinemas</h1>
      <table className="table table-dark table-striped">
        <thead>
          <tr>
            {
              Object.keys(this.state.movies[0]).map((elem, ind) => {
                return (
                  <th 
                    key={ind} 
                    onClick={() => this.handleSort(elem)}
                    style={{cursor: 'pointer'}}
                  >
                    {elem}
                    {this.state.sortKey === elem && (this.state.sortOrder === 'desc' ? ' ↓' : ' ↑')}
                  </th>
                )
              })
            }
            <th>stars</th>
          </tr>
        </thead>
        <tbody>
            { 
              this.state.movies.map((elm,index) => {
                return <tr key={elm.id}>
                  <td>{elm.id}</td>
                  <td>
                    {elm.name}
                    <button className="btn btn-primary ms-4" onClick={() => this.remove(index)}>del</button>
                  </td>
                  <td>{elm.date}</td>
                  <td>{elm.time}</td>
                  <td>{elm.genre}</td>
                  <td>{elm.rating}</td>
                  <td>
                    {this.star(elm.rating)}
                    <button className="btn btn-primary ms-4" onClick={() => this.increment(elm)}>Increment</button>
                    <button className="btn btn-primary ms-4" onClick={() => this.decrement(elm)}>Decrement</button>
                  </td>
                </tr>
              })
            }
        </tbody>
      </table>
    </>
  }
}

export default App

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 09:41:19