【问题标题】:Why does clicking on a tab that changes state and has nothing to do with ajax call creates that ajax call?为什么单击更改状态且与 ajax 调用无关的选项卡会创建该 ajax 调用?
【发布时间】:2016-08-29 14:42:18
【问题描述】:

我有一个简单的布局。

<Navbar> 中有一个<StateSelector> 点击执行一个方法。

<StateSelector> 中该按钮的 innerHTML 值作为参数传递给作为道具传递给它的函数。 parent 中存在的方法将activeOption 状态更改为All, Offline and online,具体取决于单击的按钮。

现在,这个父母又多了一个孩子,叫做<TwitchList>。这个<TwitchList> 的渲染方法包含一个包含8 个用户名的数组,并且对twitch.tv 进行了8 次调用以获取这些通道的数据。

请注意,我还没有链接<StateSelector>。除了<TwitchList><StateSelector> 属于同一个父对象之外,它与<TwitchList> 中的$.ajax(); 没有交互。

为什么单击<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

【问题讨论】:

    标签: javascript jquery ajax reactjs jsx


    【解决方案1】:

    每次&lt;App&gt; 的状态发生变化时,它都会重新渲染。这包括重新渲染它的孩子(其中是&lt;TwitchList&gt;)。您的 ajax 调用是在 &lt;TwitchList&gt;render 函数中进行的,因此每次状态更改时,都会触发该 ajax 代码。

    如果您想知道为什么状态会发生变化,那是因为您有一个函数 changeActiveOption,它可以更新传递给 &lt;Navbar&gt;&lt;App&gt; 的状态,然后传递给 &lt;StateSelector&gt;

    这里要做的适当的事情是找到一个生命周期事件来进行 ajax 调用。我推荐componentWillMountcomponentWillUpdate

    看看lifecycle functions here

    【讨论】:

    • 那么什么位置更适合它呢?如果我将它移动到 App 并将检索到的数据作为道具传递,它仍然会被调用,因为 App 被重新渲染。
    • 我了解状态为何会发生变化,因为我将使用它根据所选选项创建可过滤列表。全部,离线和在线。我很困惑我应该把$.ajax()放在哪里并获得我想要的功能。
    • 这行得通。 ComponentDidMount 可能无法正常工作,因为它是在初始渲染完成后调用的。谢谢你的建议。
    【解决方案2】:

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

    【讨论】:

    • 我必须从 ajax 调用中检索到的数据中的重要数据,然后创建一个 &lt;li&gt; &lt;/li&gt; 将其推送到一个数组中并在 &lt;ul&gt; 中显示该数组。我起初尝试过这个,但后来我无法遵循这个逻辑。因为在 render 中将无法访问 componentDidMount 中的 finalList。
    • 您是否尝试过将finalList 保持在状态中,以便在它更新时您可以从渲染方法访问状态?
    • 是的,我按照 MicronXD 的建议做了。这个问题是固定的。但是现在,我创建了一个名为 finalList 的状态,并在所有 8 个 ajax 调用完成后通过执行 ``` if(finalList.length === 8) { this.setState({ finalList: finalList }); 推送整个数组。 } ``` 但它不会更新状态。我会找到我的路的。非常感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    相关资源
    最近更新 更多