为什么单击更改状态且与 ajax 调用无关的选项卡会创建 ajax 调用?
Why does clicking on a tab that changes state and has nothing to do with ajax call creates that ajax call?
我有一个简单的布局。
<Navbar>
中有一个<StateSelector>
点击执行方法。
<StateSelector>
中该按钮的 innerHTML 值作为参数传递给作为道具传递给它的函数。 parent 中的方法根据单击的按钮将 activeOption
状态更改为 All, Offline and online
。
现在,除了这个 parent 之外,还有一个 child 叫做 <TwitchList>
。此 <TwitchList>
的呈现方法包含一个包含 8 个用户名的数组,并且对 twitch.tv
进行了 8 次调用以获取这些频道的数据。
请注意,我还没有链接 <StateSelector>
。它与 <TwitchList>
中的 $.ajax();
没有交互,除了 <TwitchList>
和 <StateSelector>
属于同一个 parent。
为什么单击 <StateSelector>
中的元素会生成 ajax 调用?
单击它一次会产生 8 次调用,这等于 usersList[] 中的用户数。
我已经尝试搜索这个问题并且我已经尝试解决了大约 4 天,但我只是不明白为什么会这样。
var Navbar = React.createClass({
render: function () {
return (
<div className="navbar">
<h1 className="header">TWITCH STREAMERS</h1>
<StateSelector changeActiveOption={this.props.changeActiveOption}/>
</div>
);
}
});
var StateSelector = React.createClass({
changeOption: function (e) {
this.props.changeActiveOption(e.target.innerHTML.toLowerCase());
},
render: function () {
return (
<div className="selectorList">
<div className="selector" onClick={this.changeOption}>ALL</div>
<div className="selector" onClick={this.changeOption}>ONLINE</div>
<div className="selector" onClick={this.changeOption}>OFFLINE</div>
</div>
);
}
});
var TwitchList = React.createClass({
render: function () {
var userslist = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
var finalList = [];
function makeURL(user, type) {
return "https://api.twitch.tv/kraken/" + type + "/" + user;
}
userslist.forEach(function (user) {
$.ajax({
url: makeURL(user, "streams"),
dataType: 'jsonp',
success: function (data) {
function getID(data) {
if (data.stream) {
return data.stream._id;
} else {
return Math.random();
}
}
function getImage(data) {
if (!data.stream) {
return "https://dummyimage.com/50x50/ecf0e7/5c5457.jpg&text=0x3F";
}
else {
return data.stream.preview.medium;
}
}
console.log(data);
var id = getID(data);
var preview = getImage(data);
console.log(preview);
finalList.push(
<li className="twitchUser" key={id}>
<img src={preview} alt="preview"/>
</li>
)
},
fail: function (xhr, error, url) {
console.error(error + " " + xhr + " " + url);
}
});
});
return (
<div className= "twitchListWraper" >
<ul className="twitchList">
{finalList}
</ul>
</div>
)
}
});
var App = React.createClass({
getInitialState: function () {
return {
activeOption: "all"
};
},
changeActiveOption: function (option) {
this.setState({
activeOption: option
});
},
render: function () {
return (
<div className="app-root">
<Navbar changeActiveOption={this.changeActiveOption}/>
<TwitchList activeOption={this.state.activeOption}/>
</div>
);
}
});
ReactDOM.render(<App />, document.getElementById('root'));
JSBin: http://jsbin.com/sulihogegi/edit?html,css,js,console,output
每次 <App>
上的状态发生变化时,它都会重新呈现。这包括重新渲染其子项(其中 <TwitchList>
)。您的 ajax 调用是在 <TwitchList>
的 render
函数中进行的,因此每次状态更改时,都会触发 ajax 代码。
如果您想知道为什么状态会发生变化,那是因为您有一个函数 changeActiveOption
,它会更新 <App>
的状态,然后传递给 <Navbar>
传递给 <StateSelector>
.
这里适当的做法是找到一个生命周期事件,在其中进行 ajax 调用。我推荐 componentWillMount
和 componentWillUpdate
。
您不应该将 ajax 调用写入 TwitchList
组件的渲染函数,而是可以将其写入 componentDidMount
函数
我有一个简单的布局。
<Navbar>
中有一个<StateSelector>
点击执行方法。
<StateSelector>
中该按钮的 innerHTML 值作为参数传递给作为道具传递给它的函数。 parent 中的方法根据单击的按钮将 activeOption
状态更改为 All, Offline and online
。
现在,除了这个 parent 之外,还有一个 child 叫做 <TwitchList>
。此 <TwitchList>
的呈现方法包含一个包含 8 个用户名的数组,并且对 twitch.tv
进行了 8 次调用以获取这些频道的数据。
请注意,我还没有链接 <StateSelector>
。它与 <TwitchList>
中的 $.ajax();
没有交互,除了 <TwitchList>
和 <StateSelector>
属于同一个 parent。
为什么单击 <StateSelector>
中的元素会生成 ajax 调用?
单击它一次会产生 8 次调用,这等于 usersList[] 中的用户数。
我已经尝试搜索这个问题并且我已经尝试解决了大约 4 天,但我只是不明白为什么会这样。
var Navbar = React.createClass({
render: function () {
return (
<div className="navbar">
<h1 className="header">TWITCH STREAMERS</h1>
<StateSelector changeActiveOption={this.props.changeActiveOption}/>
</div>
);
}
});
var StateSelector = React.createClass({
changeOption: function (e) {
this.props.changeActiveOption(e.target.innerHTML.toLowerCase());
},
render: function () {
return (
<div className="selectorList">
<div className="selector" onClick={this.changeOption}>ALL</div>
<div className="selector" onClick={this.changeOption}>ONLINE</div>
<div className="selector" onClick={this.changeOption}>OFFLINE</div>
</div>
);
}
});
var TwitchList = React.createClass({
render: function () {
var userslist = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
var finalList = [];
function makeURL(user, type) {
return "https://api.twitch.tv/kraken/" + type + "/" + user;
}
userslist.forEach(function (user) {
$.ajax({
url: makeURL(user, "streams"),
dataType: 'jsonp',
success: function (data) {
function getID(data) {
if (data.stream) {
return data.stream._id;
} else {
return Math.random();
}
}
function getImage(data) {
if (!data.stream) {
return "https://dummyimage.com/50x50/ecf0e7/5c5457.jpg&text=0x3F";
}
else {
return data.stream.preview.medium;
}
}
console.log(data);
var id = getID(data);
var preview = getImage(data);
console.log(preview);
finalList.push(
<li className="twitchUser" key={id}>
<img src={preview} alt="preview"/>
</li>
)
},
fail: function (xhr, error, url) {
console.error(error + " " + xhr + " " + url);
}
});
});
return (
<div className= "twitchListWraper" >
<ul className="twitchList">
{finalList}
</ul>
</div>
)
}
});
var App = React.createClass({
getInitialState: function () {
return {
activeOption: "all"
};
},
changeActiveOption: function (option) {
this.setState({
activeOption: option
});
},
render: function () {
return (
<div className="app-root">
<Navbar changeActiveOption={this.changeActiveOption}/>
<TwitchList activeOption={this.state.activeOption}/>
</div>
);
}
});
ReactDOM.render(<App />, document.getElementById('root'));
JSBin: http://jsbin.com/sulihogegi/edit?html,css,js,console,output
每次 <App>
上的状态发生变化时,它都会重新呈现。这包括重新渲染其子项(其中 <TwitchList>
)。您的 ajax 调用是在 <TwitchList>
的 render
函数中进行的,因此每次状态更改时,都会触发 ajax 代码。
如果您想知道为什么状态会发生变化,那是因为您有一个函数 changeActiveOption
,它会更新 <App>
的状态,然后传递给 <Navbar>
传递给 <StateSelector>
.
这里适当的做法是找到一个生命周期事件,在其中进行 ajax 调用。我推荐 componentWillMount
和 componentWillUpdate
。
您不应该将 ajax 调用写入 TwitchList
组件的渲染函数,而是可以将其写入 componentDidMount
函数