在React中进行ajax调用时无限循环?

时间:2018-03-08 21:45:32

标签: javascript arrays reactjs

我正在尝试从我拥有的阵列中获取电影列表。我循环遍历数组,将标题和海报放在屏幕上。但即使循环只发生一次,它仍然一遍又一遍地进行相同的三次api调用。我对React真的很陌生,并且认为如果有什么变化,它应该只会进行一次新的调用吗?

import React from 'react';
import $ from 'jquery';

var movieArray = ['Tarzan','1o1uyry29ddz', 'tt0120855',
'Close Encounters Of The Third Kind', 'g3hl6ewv9b7h', 'tt0075860',
'10,000 BC', 'tngmycvr418q', 'tt0443649'
];

export class Home extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '',
      poster: '',
      backdrop: '',
      genre: '',
      release: '',
      description: ''
    };
  }
componentDidUpdate(id){
    let self = this;
    let url = 'https://api.themoviedb.org/3/find/'
    let apiKey = '?api_key=<my-api-key>'
    let language = '&language=en-US'
    let imdb = '&external_source=imdb_id'
    $.ajax({
          type: 'GET',
          url: url + id + apiKey + language + imdb
    })
    .done(function(data) {
        self.setState({
          name: data.title,
          poster: data.poster_path,
          backdrop: data.backdrop_path,
          genre: data.genre_ids,
          release: data.release_data,
          description: data.overview
        });
      })
    .fail(function(jqXhr) {
      console.log('Failed to Connect to TMDB Server');
    });
}
movieLoad(){
    var arrayLength = movieArray.length;
    var movieList = [];
    var url = "http://image.tmdb.org/t/p/w185//"+this.poster ;
    for (var i = 0; i < arrayLength-2; i++) {
      this.componentDidUpdate(movieArray[i+2]);
      console.log(this.title);
      movieList.push(
        <div>
          <h1>{this.title}</h1>
          <img src= {url} />
        </div>
      );
      i = i + 2;
    }
    return movieList;
  }

  render() {
    return (
      <div>
        {this.movieLoad()}
      </div>
    );
  }
}

export default Home;

3 个答案:

答案 0 :(得分:1)

您必须编写单独的异步函数来调用Ajax请求。故意调用生命周期方法(componentDidUpdate等)是非常关键的错误。只需将Ajax调用解压缩到另一个函数,然后通过调用

来更改状态
Declare @Ids varchar(50)
Set @Ids = '1,2,3,5,4,6,7,98,234'

declare @Levels varchar(50)
set @levels='0,3'

declare @XMLLevels XML
SET @XMLLevels = CAST('<i>' + REPLACE(@Levels, ',', '</i><i>') + '</i>' AS XML)

DECLARE @XML XML
SET @XML = CAST('<i>' + REPLACE(@Ids, ',', '</i><i>') + '</i>' AS XML)

SELECT a.* 
FROM
    [AdventureWorks2012].[HumanResources].[Employee] a
    INNER JOIN @XML.nodes('i') x(i) 
        ON  a.[BusinessEntityID] = x.i.value('.', 'VARCHAR(MAX)')
    INNER JOIN @XMLlevels.nodes('i') y(i) 
        ON  a.[OrganizationLevel] = y.i.value('.', 'VARCHAR(MAX)')

如果它仍然让您感到困惑,请查看Ajax Request's in React

编辑:我假设您要多次请求。如果您只需要调用一次请求,则可以在componentDidMount()中使用它,但不能递归调用它或从其他地方再次调用它。

答案 1 :(得分:0)

您的问题就在于此代码。

componentDidUpdate(id){
    let self = this;
    let url = 'https://api.themoviedb.org/3/find/'
    let apiKey = '?api_key=7d7a79eb6ca4f02c996a7f8f0795293e'
    let language = '&language=en-US'
    let imdb = '&external_source=imdb_id'
    $.ajax({
          type: 'GET',
          url: url + id + apiKey + language + imdb
    })
    .done(function(data) {
        self.setState({
          name: data.title,
          poster: data.poster_path,
          backdrop: data.backdrop_path,
          genre: data.genre_ids,
          release: data.release_data,
          description: data.overview
        });
      })
    .fail(function(jqXhr) {
      console.log('Failed to Connect to TMDB Server');
    });

每当你再次点击setState componentDidUpdate时,由于你在didUpdate中调用setState,你就会得到一个无限循环。

您有2个选项可以解决此问题。首先,您可以将ajax请求移动到didMount生命周期方法,该方法仅在组件安装后触发一次。另一种选择,假设你有理由使用didupdate,可能会检查是否有任何事实已经改变,只有在有理由时才调用setState

对于大多数常见用例,选项1是可行的方法。

答案 2 :(得分:0)

此处的问题是您在movieLoad函数中调用render的方式 - 每次呈现时,都会调用movieLoad,调用componentDidUpdate,这将通过setState更新组件状态,这将导致组件重新渲染,这将调用movieLoad,....你可以看到它的去向。

关键是独立于render方法更新您的状态。 React提供了几种方法:

  1. 以响应事件 - 例如,如果您有一个要点击的按钮,则会触发一个事件,该事件会调用状态更新的onClick事件处理程序。然后,render方法被React 称为以更新组件。

  2. 首次加载组件时 - 在componentDidMount方法中。您可以在此处致电setState当它准备就绪后,React会致电render

  3. 当组件从父级接收新属性时 - 在componentWillReceiveProps方法中。然后,您可以通过setState使用新道具更新状态,并通过React调用 render

  4. 要详细了解这些内容,请查看State and Lifecycle section of the React docs

    关键是,当您使用setState方法更新组件状态时,让React负责渲染,并且在渲染时不要尝试更改状态。