Why is HTML5 drawImage not drawing images on canvas?

Here is my code, please help. I have tried adding an eventListener to draw the image only after the image has loaded. I have also tried placing the event listener before and after setting the image src but still nothing seems to work. I need a solution asap.

I just cant seem to figure out exactly what’s causing this. Can someone explain please.

import React from 'react';
import {useEffect, useState} from 'react';

function Main() {
    //initiate state
    const [ plane, setPlane ] = useState( new Image() );
    const [ star, setStar ] = useState( new Image() );
    const [ bird, setBird ] = useState( new Image() );
    const [ parachute, setParachute ] = useState( new Image() );
    const [ cloud, setCloud ] = useState( new Image() );
    
    //draw the game animation
    let draw = () => {
        const canvas = document.getElementById('canvas');
        const context = canvas.getContext('2d'); //context

        //set background color
        //context.fillStyle = '#74b9ff';
        //context.fillRect(0, 0, canvas.width, canvas.height);

        //load images
        plane.onload = drawImage( context);
        plane.src = 'images/plane.png';
        star.src = 'images/star.png';
        bird.src = 'images/bird.png';
        parachute.src = 'images/parachute.png';
        //cloud.src = 'images/cloud.png';
        // setPlane( prevState => { return {...prevState, src: 'images/plane.png' }  } );
        // setStar( prevState => { return {...prevState, src: 'images/star.png' }  } );
        // setBird( prevState => { return {...prevState, src: 'images/bird.png' }  } );
        // setParachute( prevState => { return {...prevState, src: 'images/parachute.png' }  } );
        // setCloud( prevState => { return {...prevState, src: 'images/cloud.png' }  } );
        
        

    }

    let drawImage = ( context ) => {
        context.drawImage(plane, 0, 0, 50, 50);
    }

    useEffect( () => draw(), [] );

    return (
        <div className="container">
            <canvas width='400px' height='400px' id='canvas'></canvas>
        </div>
    );
}

export default Main;

Someone gave me a perfect answer over at stackoverflow. It is as follows:

It might not be obvious but your issue is caused by the following line:

plane.onload = drawImage( context);

If written that way, it simply doesn’t do what you might think. The onload event can be assigned a callback function - which as the name implies - fires a function as soon as something finished loading. If you append parentheses () , it will actually execute the function right away .

That means it will try to draw the image before it even finished loading.

What you need to to is pass a reference to your function by it’s name only.

plane.onload = drawImage;

The problem in your case is that you want to pass a parameter. This can’t be done - at least not in this way.

What you can do however is making the context a property of the Image object itself.

Something like:

let draw = () => {
    const canvas = document.getElementById('canvas');
    const context = canvas.getContext('2d'); //context

    context.fillStyle = '#74b9ff';

    plane.context=context;
    plane.onload = drawImage;        
    plane.src = 'images/plane.png';
}

let drawImage = ( e ) => {
  e.target.context.drawImage(plane, 0, 0, 50, 50);
}

The link is: