dmc91 dmc91 - 7 months ago 25
Javascript Question

Saving an array to state?

I'm building an

RSS
reader based upon the
CommentBox
example on the react website.

When attempting to save the results from the google feed API to state, the state is not being succesfully saved outside of the jQuery ajax function, where I can read out the variable to
console.log
and the resulting information is correct but when I read out the state outside of the function it's printing out the empty array this is initiated when the component is first called.

var RSSApp = React.createClass({
getInitialState: function () {
return {feed:[]};
},
componentDidMount: function () {
this.loadRssFeed();
},
loadRssFeed: function() {
$.ajax({
url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=-1&q=' + encodeURIComponent(this.props.url),
dataType: "jsonp",
jsonCallback: "reponseData",
success: function(feed) {
var feeds = feed.responseData.feed.entries;
console.log(feeds)
console.log(feed.responseData.feed)
this.setState({feeds:feed});
}.bind(this)
});
console.log(this.state)
},
render: function () {
return (
<div className="RSSBox">
<h1>RSS Feed built using ReactJS</h1>
<RSSForm />
<RSSList data={this.state.feed} />
</div>
)
}
});


Where am I going wrong in saving the state?

Answer

The problem with your code is that you are trying to access the state before it is set.

$.ajax call is asynchronous and non-blocking which means that the console.log(this.state) is executed before the data is actually returned from the server. In order to fix this change your code to look like this (I added some probably useful comments):

var RSSApp = React.createClass({
getInitialState: function () {
    return {feed:[]};
},
componentDidMount: function () {
    this.loadRssFeed();
},
loadRssFeed: function() {
    $.ajax({
        url: 'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=-1&q=' + encodeURIComponent(this.props.url),
        dataType: "jsonp",
        jsonCallback: "reponseData",
        success: function(feed) {
            // the success callback is executed asynchronously after some time (time required to get the data from server)
            var feeds = feed.responseData.feed.entries;
            console.log(feeds)
            console.log(feed.responseData.feed)
            this.setState({feeds:feed});

            console.log(this.state); // <-- this should work, continue with state manipulation here
        }.bind(this)
    });
    // console.log(this.state) -- this will be executed before the data is returned from the server as previous call $.ajax is non-blocking
},
render: function () {
    return (
        <div className="RSSBox">
            <h1>RSS Feed built using ReactJS</h1>
            <RSSForm />
            <RSSList data={this.state.feed} />
        </div>
    )
}
Comments