FRANKfisher
FRANKfisher

Reputation: 121

React.js. How to change keyword 'this'

i am trying to get every image download URL from Firebase. It seems that the first 'this' is different from the second one. If i want to let the second 'this' equals to the value of the first, what should i do? Thank you so much!

getAllURL = product => {

    // Get all the images from the firebase  
    var storage = firebase.storage();
    console.log(this) // first this
    const storageRef =  storage.ref(`image/${product}`)

    storageRef.listAll().then(function(result) {         
      result.items.forEach(function(imageRef) {
            imageRef.getDownloadURL().then(function(url) {
             console.log(this) // second this is undefined
            }).catch(function(error) {});        
     })
   })   

  }





componentDidMount() {
    axios.get('/user/product')
        .then(res=>{
            if(res.data.code==0) {
                this.setState({data:res.data.data},function(){                      
                    for (var i = 0; i < this.state.data.length; i++){ 
                        this.getAllURL(this.state.data[i].productName)  
                    }                     
                 })
            }
        })
 }  

Upvotes: 0

Views: 64

Answers (1)

Montri M
Montri M

Reputation: 1766

this is one the most confusing features in Javascript. I'd recommended you to look more into the topic.

As for a shortcut, there're many ways to take care of that.

First method: just assigned the first this into some variable first.

getAllURL = product => {

    // Get all the images from the firebase  
    var storage = firebase.storage();
    console.log(this) // first this
    var firstThis = this; // some people prefered to assign "var that = this;", lol
    const storageRef =  storage.ref(`image/${product}`)

    storageRef.listAll().then(function(result) {         
        result.items.forEach(function(imageRef) {
            imageRef.getDownloadURL().then(function(url) {
                 console.log(firstThis); // use the new variable to refer to the firstThis
            }).catch(function(error) {});        
        });
    });
}

Second method: make use of bind function in javascript (a bit more advanced, and much better received from a functional programming perspective)

getAllURL = product => {

    // Get all the images from the firebase  
    var storage = firebase.storage();
    console.log(this) // first this
    const storageRef =  storage.ref(`image/${product}`)

    storageRef.listAll().then((function(result) {         
        result.items.forEach((function(imageRef) {
            imageRef.getDownloadURL().then((function(url) {
                 console.log(this);
            }).bind(this)).catch(function(error) {}); // yet another binding to propagate "this" inside
        }).bind(this)); // another binding to force "this" on this yet another inline function to equal the first this (propagate it down)
    }).bind(this)); // this binding will force "this" inside this inline function to equals the firstThis
}

Note: It might get less confusing if amount of inline functions is reduced

getAllURL = product => {

    // Get all the images from the firebase  
    var storage = firebase.storage();
    console.log(this) // first this
    const storageRef =  storage.ref(`image/${product}`)

    storageRef.listAll().then(listAllCallback.bind(this));
}

function listAllCallback(result) {
    for (var i = 0; i<result.items.length; i++) {
        var imageRef = result.items[i];
        imageRef.getDownloadURL()
            .then(downloadUrlCallback.bind(this))
            .catch(function(error) {});
    }
}

function downloadUrlCallback(url) {
    console.log(this); // second this
}

Upvotes: 1

Related Questions