为什么单击更改状态且与 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 调用。我推荐 componentWillMountcomponentWillUpdate

看看lifecycle functions here

您不应该将 ajax 调用写入 TwitchList 组件的渲染函数,而是可以将其写入 componentDidMount 函数