davidfig / pixi-viewport

A highly configurable viewport/2D camera designed to work with pixi.js
https://davidfig.github.io/pixi-viewport/
MIT License
1.04k stars 174 forks source link

Problem with viewport.destroy() when React component gets dismounted #473

Open darotar opened 9 months ago

darotar commented 9 months ago

I've experienced a problem when I was destroying the viewport on component dismounting in React

the dismount logic is pretty straight-forward:

React.useEffect(() => {
   return () => {
      viewport.destroy();
   };
})

The problem occurs connected with removing event listeners from domElement when destroying - as in React dismounting, markup's being removed from DOM first and side effects get done secondy, thus it throws the error that there's no "removeEventListener" of "undefined", domElement doesn't exist already

image

As my current workaround, I'm just adding fake domElement because I see these final steps are only related to event listeners removing and they were blocking further going to super.destroy() part

React.useEffect(() => {
   return () => {
      let div = document.createElement('div');

      if (!viewport.options.events.domElement) {
         viewport.options.events.domElement = div;
      }

      viewport.destroy({
         children: true,
         texture: true,
         baseTexture: true,
      });

      div = undefined;
   }
});

I don't consider it a viewport library issue, as viewport's flow just wants to make things in right order, just was wondering if there's still some adjustments required that would allow to avoid such issues.

E.g. I could raise a small PR for checking existance of domElement while trying to destroy eventListeners

Thank you

ArthurTimofey commented 9 months ago

Not sure if it will fix this for you but im just dismount the stage instead.

s0rta commented 8 months ago

Arthur is there a way to do that using the React Pixi stage component?

ArthurTimofey commented 8 months ago

Arthur is there a way to do that using the React Pixi stage component?

Yup, you can use the key prop for the stage, set that key string in a state and update the key using set state to another value to cause re render of the canvas.