0

I have a class called PhotoTags that has a function called getScalePercent(). In getScalePercent I do a simple calculation involving the width and height of a displayed image, and return a value. In the render function of PhotoTags I use coordinate data to apply elements over a photo. This logic works fine only if the image has been loaded 100%. If I refresh the page enough times I can see that my logic is in fact setting the coordinates properly but only once the image has either been cached, or loaded quickly. Therefore I want to use imagesLoaded to check if the image has loaded, inorder to use the coordinates effectively.

My function looks like this:

getScalePercent(){
        var p =0;
        var targetWidth = $('.expanded-image').width();
        var targetHeight = $('.expanded-image').height();
        p = (targetWidth / 1920);
        return p;
}

And in my render function I am trying to use imagesLoaded to check if the image has been loaded before using getScalePercent():

render(){
   var p = 0;

   $('.expanded-image').imagesLoaded().done( function() {
        p = this.getScalePercent();
   });

   console.log(p); //But value is still 0

   //I then want to use p later in the render function

My variable p is not being manipulated within the .done event of imagesLoaded. I know it has something to do with asynchronous calls and what not, and I have tried putting imagesLoaded in getScalePercent() but to no avail. I have also tried doing a callback to getScalePercent() and many other variations but still to no avail. Basically what I want to do is fire getScalePercent() inside the .done() event of imagesLoaded. I then want to be able to use the value that getScalePercent() returns (when the image is fully loaded) inside the render function of PhotoTags. Any help is much appreciated.

connected_user
  • 814
  • 1
  • 9
  • 25
  • So you have to set your logic using `p` inside `done` callback or call from it a function passing `p` as parameter – A. Wolff Aug 30 '16 at 15:37
  • http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Roamer-1888 Aug 31 '16 at 22:16

2 Answers2

1

Would you not be better just adding an onLoad event on your image, something like this:

class Test extends Component {
    constructor (props){
        super(props);
        this.state = {
            imgLoaded:false
        }
    }
    handleImgLoaded (event){
        // Do stuff
        console.log(event.target);
        this.setState({
            imgLoaded:true
        });
    }
    render (){           
        <div className={'img-wrapper-class ' + (this.state.imgLoaded ? 'img-loaded' : 'img-loading')}>
            <img src={"somesrc.jpg"} onLoad={this.handleImgLoaded.bind(this)} />
        </div>
    }
}
Giuseppe
  • 288
  • 2
  • 12
  • does onLoad fire when the image starts loading or when the image has fully loaded? – connected_user Aug 30 '16 at 15:52
  • It fires once it has loaded, so you can use it for showing / hiding loading animations etc.. Just in addition.. you can obviously access the event and the event target in the callback, so you should be able to get all of the info you need on widths etc.. edited the example to show this... – Giuseppe Aug 30 '16 at 15:53
  • Thank you! I believe this is the most correct answer so far. I need to think in React more. All I did was add a imageLoaded state to the component containing the image, and only rendered PhotoTags when the imageLoaded state was true. The imageLoaded state gets set to true through a function that fires in onLoad on the image in question. Thanks! – connected_user Aug 30 '16 at 16:58
  • Sounds good, yeah it takes a bit of time to get your head into the correct way of thinking, I was the same but you'll soon pick it up and then you're good to go. Glad you got it working. – Giuseppe Aug 31 '16 at 11:47
  • Edit - thought I'd add a bit more detail to the example showing how I deal with loading image states / loading animations.. Hopefully help anyone that comes across this a little more. – Giuseppe Aug 31 '16 at 11:53
0

Fairly sure the problem here is that the DOM element .expanded-image isn't actually loaded in the DOM on the first render. Try moving this logic to componentDidMount and it should work fine. You'll also want to save p in state so that you can reference it outside of componentDidMount, give it an initial value, and rerender you component immediately if it changes.

taylorc93
  • 3,676
  • 2
  • 20
  • 34
  • I think you are right. I will try it and comment back my results. It seems I am probably not thinking in "React" when approaching this functionality. – connected_user Aug 30 '16 at 15:44
  • Thanks for the feedback however I think Giuseppe's answer, combined with having an imageLoaded state test, fits the React narrative better. – connected_user Aug 30 '16 at 17:05