TypeError: Cannot read properties of undefined (reading '_elements')

I tried to remove a div inside the set timeout function but it give me the error in the title.

Here is the stack trace:

TypeError: Cannot read properties of undefined (reading '_elements')
    at f.default.Element.remove (https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js:3:520693)

I’m currently in instance mode if you need to know

I could not make a MWE but my live code is right here

The code that is seemingly causing the issue is on line 438 with the code being this:

// Remove eveything if it is done loading
if ( FilesFullyLoaded || p.LoadPercent >= 100 ) {
	
	FilesFullyLoaded = true;																									// Sets FilesFullyLoaded to true

	p.LoadingText.html("Loading... DONE!!");																					// Tells the user that the loading is done

	p.noLoop();																													// Stops the draw loop from looping
			
	setTimeout(p.LoadingDiv.remove, 750);	// <-- This line																	// Deletes div to make it disapere
			
} 
else {
	p.LoadingText.html(`Loading... ${p.round(p.LoadPercent)}%`)																	// Inform the user of the percentage of files loaded
}

I know this because every time I remove the line its fixed.

I don’t think we can use method remove() over a p5.Element which has been created via select() b/c it refers to an already existing HTMLElement.

Instead it’s used for createXXX() named functions such as createElement().

So i cant do it or what?

That may be true BUT when I use the .remove() method without the setTimeout() it works.

Oh, I thought it’d be that. But on a 2nd look I’ve spotted the obvious here:

For any function which depends on the keyword this (as methods normally do) we have to be watchful whether the object invoking it is the correct 1, b/c that becomes the this inside a function.

In the case of p.LoadingDiv.remove, remove()'s preceding property LoadingDiv contains the correct object which becomes the caller object when we manually invoke it like this:
p.LoadingDiv.remove();

However, when we pass the expression p.LoadingDiv.remove to setTimeout() as its callback, it’s not LoadingDiv which is gonna invoke remove() anymore:

As an archaic workaround we could use method bind() in order to clone the method w/ a fixed this:
setTimeout(p.LoadingDiv.remove.bind(LoadingDiv), 750);

But for modern JS, a wrapper function using the fat arrow expression syntax is the usual pick instead:
setTimeout(() => p.LoadingDiv.remove(), 750);

P.S.: By JS (and Java) convention, regular variables, parameters & properties should use the lowerCamelCase style.
So property LoadingDiv is better off renamed as loadingDiv.

1 Like

THANK YOU SO MUCH :smiley:

I have a specific way to formate my vars so LoadingDiv really means it’s a “globe” var (for the p namespace) and it can change, like a let.