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

如何从TMDB API获取并渲染3条电影数据?TS类型校验求助

问题解决:无法渲染TMDB热门电影数据 + TypeScript类型校验优化

一、渲染失败的核心原因及修复

你的代码无法渲染数据,主要存在两个关键问题:

1. map回调未返回元素

在topThree.map的箭头函数中,你使用大括号包裹逻辑但没有显式returnJSX元素,导致每个循环迭代都返回undefined,页面自然没有内容。

修复方式二选一:

  • 去掉大括号,用括号包裹JSX(箭头函数隐式返回):
{topThree.map((movie) => (
  <>
    <h1>{movie.id}</h1>
    <p>{movie.title}</p>
  </>
))}
  • 保留大括号,添加return关键字:
{topThree.map((movie) => {
  return (
    <>
      <h1>{movie.id}</h1>
      <p>{movie.title}</p>
    </>
  );
})}

2. 多余的Object.entries处理

TMDB返回的data.results本身就是电影对象数组,不需要用Object.entries转成键值对数组,直接截取前3项即可:

// 原代码
setTopThree(Object.entries(data.results).slice(0,3).map(entry => entry[1]));
// 修复后
setTopThree(data.results.slice(0, 3));

额外优化:利用loading状态

你定义了loading但未使用,可添加加载状态提示,避免页面空白:

useEffect(()=>{
  const url = `https://api.themoviedb.org/3/movie/popular?api_key=${process.env.MOVIE_API}`;
  axios(url)
    .then(({data}) => {
      setTopThree(data.results.slice(0, 3));
      setLoading(false); // 请求成功后结束加载
    })
    .catch(err => {
      console.log(err.message);
      setLoading(false); // 请求失败也结束加载
    });
},[]); 

// 修改return逻辑
if (loading) return <div>加载中...</div>;
if (!topThree) return <div>暂无数据</div>;

return (
  <>
    {topThree.map((movie) => (
      <>
        <h1>{movie.id}</h1>
        <p>{movie.title}</p>
      </>
    ))}
    <div className="absolute top-[15%] left-[10%]"></div>
  </>
);

二、TypeScript类型校验优化

你已经定义了基础接口,接下来可以进一步完善并应用到代码中,替换any类型:

1. 完善接口(匹配TMDB返回字段)

根据TMDB官方API规范,调整接口字段的可选性(比如title是必返回字段,不需要加?):

interface IMovie {
  id: number;
  original_title: string;
  title: string;
  poster_path: string | null;
  backdrop_path: string | null;
  genre_ids: number[];
  // 可根据需求添加其他字段,比如vote_average、release_date等
}

2. 指定State类型

将topThree和movies的State类型从any[] | null替换为IMovie[] | null:

const [movies, setMovies] = useState<IMovie[] | null>(null);
const [topThree, setTopThree] = useState<IMovie[] | null>(null);

3. 给Axios请求指定返回类型

让Axios明确知道返回数据的结构,避免类型推断错误:

axios.get<{ results: IMovie[] }>(url)
  .then(({data}) => {
    setTopThree(data.results.slice(0, 3));
    setLoading(false);
  })

修复后的完整代码

import { useEffect, useState } from 'react';
import axios from 'axios';

interface IMovie {
  id: number;
  original_title: string;
  title: string;
  poster_path: string | null;
  backdrop_path: string | null;
  genre_ids: number[];
}

function Carousel() {
  const [movies, setMovies] = useState<IMovie[] | null>(null);
  const [topThree, setTopThree] = useState<IMovie[] | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(()=>{
    const url = `https://api.themoviedb.org/3/movie/popular?api_key=${process.env.MOVIE_API}`;
    axios.get<{ results: IMovie[] }>(url)
      .then(({data}) => {
        setTopThree(data.results.slice(0, 3));
        setLoading(false);
      })
      .catch(err => {
        console.log(err.message);
        setLoading(false);
      });
  },[]); 

  if (loading) return <div>加载中...</div>;
  if (!topThree) return <div>暂无数据</div>;

  return (
    <>
      {topThree.map((movie) => (
        <>
          <h1>{movie.id}</h1>
          <p>{movie.title}</p>
        </>
      ))}
      <div className="absolute top-[15%] left-[10%]"></div>
    </>
  );
}

export default Carousel;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:35:15