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

在React useEffect中使用TypeScript对电影对象数组排序遇阻求助

解决React useEffect中电影数组排序的TypeScript类型问题

我来帮你拆解并解决这两个TypeScript错误,同时优化你的排序逻辑:

先分析错误原因

  1. 返回布尔值的错误
    你把sortArray定义成了类型谓词函数(返回sortProperty is keyof typeof types),这类函数的作用是做类型判断,必须返回boolean,但你却在函数里返回了排序后的数组,自然会触发类型不匹配的报错。这个函数的定位完全错了,它应该是一个返回排序后数组的工具函数,而非类型守卫。

  2. 索引类型错误
    之前sortProperty是string类型,TypeScript无法确认这个字符串是否是Movie接口的合法属性键,所以不允许用来索引Movie对象。你需要把排序属性的类型限定为keyof Movie,才能让TypeScript确认索引的安全性。


修正后的完整代码

我会用更符合React最佳实践的方式重构你的代码,同时解决类型问题:

import React, { useState, useEffect, useMemo } from 'react';
import { useHistory } from 'react-router-dom';
import Requests from './Requests';

export interface Movie { 
  comments: string; 
  imdb: string; 
  mtc: string; 
  rtc: string; 
  smn: string; 
  title: string; 
}

const Database = () => {
  const [movies, setMovies] = React.useState<Movie[]>([]);
  // 把排序类型限定为Movie的属性键,从根源避免无效属性传入
  const [sortConfig, setSortConfig] = useState<{
    key: keyof Movie;
    direction: 'asc' | 'desc';
  }>({ key: 'title', direction: 'asc' });
  const history = useHistory();

  // 仅在组件挂载时请求一次电影数据
  useEffect(() => {
    Requests.getMovies()
      .then(fetchedMovies => setMovies(fetchedMovies))
      .catch(err => console.error('获取电影数据失败:', err));
  }, []);

  // 用useMemo缓存排序结果,只有movies或sortConfig变化时才重新排序
  const sortedMovies = useMemo(() => {
    if (movies.length === 0) return [];

    return [...movies].sort((a, b) => {
      const valueA = a[sortConfig.key];
      const valueB = b[sortConfig.key];

      // 区分字符串和数字字符串的排序逻辑
      if (sortConfig.key === 'title') {
        // 标题按字母顺序排序
        const compareResult = valueA.localeCompare(valueB);
        return sortConfig.direction === 'asc' ? compareResult : -compareResult;
      } else {
        // 评分/评论数字符串转成数字比较
        const numA = parseFloat(valueA);
        const numB = parseFloat(valueB);
        const compareResult = numA - numB;
        return sortConfig.direction === 'asc' ? compareResult : -compareResult;
      }
    });
  }, [movies, sortConfig]);

  // 切换排序规则的工具函数(支持升序/降序切换)
  const handleSortChange = (key: keyof Movie) => {
    let direction: 'asc' | 'desc' = 'asc';
    if (sortConfig.key === key && sortConfig.direction === 'asc') {
      direction = 'desc';
    }
    setSortConfig({ key, direction });
  };

  return (
    <div>
      {/* 排序选择栏(支持多属性+升降序切换) */}
      <div className="sort-controls">
        <button onClick={() => handleSortChange('title')}>
          标题 {sortConfig.key === 'title' && (sortConfig.direction === 'asc' ? '↑' : '↓')}
        </button>
        <button onClick={() => handleSortChange('imdb')}>
          IMDB评分 {sortConfig.key === 'imdb' && (sortConfig.direction === 'asc' ? '↑' : '↓')}
        </button>
        <button onClick={() => handleSortChange('rtc')}>
          烂番茄评分 {sortConfig.key === 'rtc' && (sortConfig.direction === 'asc' ? '↑' : '↓')}
        </button>
      </div>

      {/* 渲染排序后的电影列表 */}
      <div className="movie-list">
        {sortedMovies.map(movie => (
          <div key={movie.imdb} className="movie-card">
            <h3>{movie.title}</h3>
            <p>IMDB: {movie.imdb} | 烂番茄: {movie.rtc}</p>
            <p>评论数: {movie.comments}</p>
          </div>
        ))}
      </div>
    </div>
  );
};

export default Database;

关键优化点说明

  1. 类型安全强化:把sortConfig.key的类型限定为keyof Movie,确保只能传入Movie接口中定义的属性,彻底解决索引类型错误。
  2. 用useMemo替代useEffect排序:避免在副作用里直接修改状态,同时缓存排序结果,提升性能(只有依赖项变化时才重新排序)。
  3. 支持多属性+升降序扩展:通过sortConfig对象同时记录排序属性和方向,后续扩展其他属性排序只需要添加对应的按钮和逻辑即可。
  4. 区分不同类型的排序逻辑:标题用字符串的localeCompare做字母排序,评分/评论数转成数字后做数值排序,确保排序行为符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:27:37