【问题标题】:Unable to access Api call data. Returns undefined. React无法访问 Api 调用数据。返回未定义。反应
【发布时间】:2019-02-28 20:03:08
【问题描述】:

我正在尝试使用 React 制作电影搜索应用,并已对电影数据库 API 进行了 API 调用。我想要做的是获取新电影版本的数据,然后进行另一个 API 调用以获取每个新版本的具体细节,因为这些数据存储在不同的位置。

我能够从第一个 API 调用访问数据,但是当我尝试从第二个数据对象访问电影标语时,控制台输出“无法读取未定义的属性‘标语’”。

App.js

  class App extends Component {
    constructor(props) {
      super(props)
      this.state = {
        movieRows: [],
        ids: [],
        movieDetails: [],
      }
      this.performSearch = this.performSearch.bind(this);        
    }

    componentDidMount() {
      this.performSearch();
    }

    performSearch() {
      const urlString = "https://api.themoviedb.org/3/movie/popular?api_key=6db3cd67e35336927891a72c05&language=en-US&page=1";
      axios.get(urlString)
        .then(res => {

          const results = res.data.results
          let movieRows = [];
          let movieDetails = [];

          results.forEach((movie) => {

            movieRows.push(movie);
            axios.get(`https://api.themoviedb.org/3/movie/${movie.id}?api_key=6db3cd67e35336927891a72c05&language=en-US`)
            .then(res => {
              movieDetails.push(res.data);
            })
            .catch(function (error) {
              console.log(error);
            });
          });

          this.setState({
            movieRows: movieRows,
            movieDetails: movieDetails,
          });
        })
        .catch(function (error) {
          console.log(error);
        });  
    }

Content.js

export default class Content extends Component {
    constructor(props) {
        super(props)
        this.state = {
            name: 'Jonathan',
        }
        this.filmLoop = this.filmLoop.bind(this);
    }

    filmLoop() {

        let movieData = this.props.globalState.movieRows;
        let movieDetails = this.props.globalState.movieDetails;

        return movieData.map((movie, index) => {

            return (
                <div className="film" key={index}>
                    <img className="poster" src={`http://image.tmdb.org/t/p/w342${movie.poster_path}`} alt="The Dark Knight poster" />
                    <div className="film-info">
                        <div className="film-title">
                            <h3>{movie.title}</h3>
                        </div>
                        <h4>{movieDetails[index].tagline}</h4>

*我从最后一行得到错误

【问题讨论】:

  • 你的 setState 在movieDetails 被填充之前运行。这当然会导致 movieDetails[index].tagline 失败,因为该索引处没有任何内容。
  • 感谢您帮助我理解问题。现在,在填充了 movieDetails 后,我将如何让 setState 运行?
  • 您可以将所有 axios 承诺收集到一个数组中,然后使用 promise.all 来检测它们何时全部完成
  • 好的,我去试试。
  • 经过几个小时的尝试,我得到了它的工作。现在我觉得我更好地理解了承诺。谢谢凯文!

标签: reactjs themoviedb-api


【解决方案1】:

主要问题是您在.then 之外调用setState,您必须更新thencatch 内部的状态。这是因为promise 是一个async 函数,所以只有当promise 被resolved 或rejected 时才需要改变状态。

performSearch() {
      const urlString = "https://api.themoviedb.org/3/movie/popular?api_key=6db3cd67e35336927891a72c05&language=en-US&page=1";
      axios.get(urlString)
        .then(responsePopular => {

          const results = responsePopular.data.results
          let movieRows = [];
          let movieDetails = [];

          results.forEach((movie) => {

            movieRows = [...movieRows, movie];

            axios.get(`https://api.themoviedb.org/3/movie/${movie.id}?api_key=6db3cd67e35336927891a72c05&language=en-US`)
            .then(responseMovie => {
              movieDetails = [...movieDetails, responseMovie.data];
              this.setState({
                movieRows: movieRows,
                movieDetails: movieDetails,  
              })

            })
            .catch(function (error) {
              console.log(error);
            });
          });

        })
        .catch(function (error) {
          console.log(error);
        });  
    }

我认为这可以解决您的问题。

【讨论】:

    猜你喜欢
    • 2017-04-27
    • 2021-06-05
    • 2018-04-16
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多