我正在尝试从我拥有的阵列中获取电影列表。我循环遍历数组,将标题和海报放在屏幕上。但即使循环只发生一次,它仍然一遍又一遍地进行相同的三次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;
答案 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提供了几种方法:
以响应事件 - 例如,如果您有一个要点击的按钮,则会触发一个事件,该事件会调用状态更新的onClick
事件处理程序。然后,render
方法被React 称为以更新组件。
首次加载组件时 - 在componentDidMount
方法中。您可以在此处致电setState
,当它准备就绪后,React会致电render
当组件从父级接收新属性时 - 在componentWillReceiveProps
方法中。然后,您可以通过setState
使用新道具更新状态,并通过React调用 render
要详细了解这些内容,请查看State and Lifecycle section of the React docs。
关键是,当您使用setState
方法更新组件状态时,让React负责渲染,并且在渲染时不要尝试更改状态。