0

I am trying to understand, i know when i console.log(pictures) i get the end result

and when i "console.log(JSON.stringify(pictures))" i get the current one at that moment.

why does in that moment when it logs the second option, the array is empty and in the end it got a value,

how can i force the synchronization of the value and this.state

the problem is that when i am sending in the end:

ImageList pics={this.state.picturesArr} />

it is being sent empty

let pictures = [];
let urls =[];
let titles=[];
let nextpage ='';
let pageback='';

class App extends Component {

    constructor(props) {
        super(props);

        this.state = {
            picturesArr: [],
            urlArr: [],
            titleArr:[],
            nextPage:'',
            prevuisPage:''
        };

        this.loadSubreddit = this.loadSubreddit.bind(this);
    }

    loadSubreddit(subre) {

        reddit.hot(subre).limit(5).fetch(function(res) {
            console.log(res);
            nextpage = res.data.after.toString();
            // pageback = res.data.before.valueOf();

            for (let i = 0; i < res.data.children.length; i++){
                pictures.push(res.data.children[i].data.url);
                urls.push(res.data.children[i].data.permalink);
                titles.push(res.data.children[i].data.title);
            }
        });

        this.setState({
            picturesArr: pictures,
            urlArr: urls,
            titleArr: titles,
            nextPage: nextpage,
            prevuisPage: pageback
        }, () => {
            console.log(this.state)
        });

        console.log(pictures);
        console.log(JSON.stringify(pictures));
    }


    componentWillMount() {
        console.log('comp is mounting');
        this.loadSubreddit('cats');
    }

    render() {
        return (
            <div className="App">
            <div className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <h2>Welcome to React</h2>
            </div>
                <Col sm={8} md={10} smOffset={2} mdOffset={1} >
                    <ImageList pics={this.state.picturesArr} />
                </Col>
            </div>
        );
    }
}

export default App;
ArneHugo
  • 6,051
  • 1
  • 26
  • 47
Ben Porat
  • 583
  • 1
  • 4
  • 6
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) you are trying to use async result in synchronous way. That is not possible. You need to call setState inside callback. – Yury Tarabanko May 03 '17 at 14:34

1 Answers1

2

In the code you provided, you call this.setState outside of the api-call callback.

You need to (1) move the code for setting state inside the callback, and (2) bind the callback function to the component instance to access its this.setState.

The fixed loadSubbreddit function is shown below.

loadSubreddit(subre) {

    reddit.hot(subre).limit(5).fetch(function(res) {
        console.log(res);
        nextpage = res.data.after.toString();
        // pageback = res.data.before.valueOf();

        for (let i = 0; i < res.data.children.length; i++){
            pictures.push(res.data.children[i].data.url);
            urls.push(res.data.children[i].data.permalink);
            titles.push(res.data.children[i].data.title);
        }

        this.setState({
            picturesArr: pictures,
            urlArr: urls,
            titleArr: titles,
            nextPage: nextpage,
            prevuisPage: pageback
        }, () => {
            console.log(this.state)
        });

        console.log(pictures);
        console.log(JSON.stringify(pictures));
    }.bind(this));
}
ArneHugo
  • 6,051
  • 1
  • 26
  • 47
  • 1
    Correct. And now `pictures` doesn't have to be a global variable. – Andre Pena May 03 '17 at 14:42
  • Thanks! so just to make sure i got my mistake, when using this.setState it needs to be with in the api callback(i need to read a bit more about it), and because another execution context is created for the inner function i need to bind "this", so it will point to the existing state – Ben Porat May 03 '17 at 14:49
  • When making api-calls in general, you need to wait for the response before you can store it. You can also use `setState` outside api-call callbacks, but not if you want to wait for the response from an api-call. – ArneHugo May 03 '17 at 15:15