Bip
Bip

Reputation: 913

React - component state not being set

Why is the output of the piece of code below "true"?

class InstagramGallery extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            images: true
        };
    }

    componentDidMount() {
        var accessToken = '*Instagram token*';
        var instagramApi = new Instagram(accessToken);
        instagramApi.userSelfMedia().then(function(result) {
            this.setState({
                images: false,
            });
        }, function(err) {
            console.log(err);
        });

    }

    render() {
        console.log(this.state.images); 
        return (
            <div className="instagram-gallery">

            </div>
        )
    }
}

From what I know, the constructor is being called first. Therefore images=true, after that it renders with console.log(true), and componentDidMount is called. After data from instagram is fetched, and I update component state which should re-render the component with images=false. Where am I wrong?

Upvotes: 2

Views: 529

Answers (3)

devserkan
devserkan

Reputation: 17608

You are using a regular function for instagramAp.userSelfMedia callback hence losing this context. Use an arrow function instead:

instagramApi.userSelfMedia().then(
  result => {
    this.setState({
      images: false
    });
  },
  function(err) {
    console.log(err);
  }
);

Regular functions create their own lexical scope, so this does not point your class in the callback function. Arrow functions don't create their own lexical scopes, to this points your component and you can use this.setState().

Using an arrow function saves you from binding your function or keeping this in another variable like:

var accessToken = "*Instagram token*";
var instagramApi = new Instagram(accessToken);
const that = this;
instagramApi.userSelfMedia().then(
  function(result) {
    that.setState({
      images: false
    });
  },
  function(err) {
    console.log(err);
  }
);

Upvotes: 4

Hemadri Dasari
Hemadri Dasari

Reputation: 33974

Because this isn’t available

Use arrow function

 instagramApi.userSelfMedia().then((result) => {
        this.setState({
            images: false,
        });
    }, function(err) {
        console.log(err);
    });

  }

Or bind it manually

  instagramApi.userSelfMedia().then(function(result) {
        this.setState({
            images: false,
        });
    }.bind(this), function(err) {
        console.log(err);
    });

  }

Upvotes: 2

Andy Lower
Andy Lower

Reputation: 35

I've not been using RN for that long but does this have an affect?

componentDidMount() {
    var accessToken = '*Instagram token*';
    var instagramApi = new Instagram(accessToken);
    instagramApi.userSelfMedia().then((result) => { //USING ARROW FUNCTION
        this.setState({
            images: false,
        });
    }, function(err) {
        console.log(err);
    });

}

I added an arrow function so that the 'this.state' doesn't get mixed up with the 'this' inside instagramApi.userSelfMedia().

Upvotes: 2

Related Questions