WebReflection / hyperHTML

A Fast & Light Virtual DOM Alternative
ISC License
3.06k stars 112 forks source link

async onconnected/ondisconnected event.target #378

Closed jaschaio closed 4 years ago

jaschaio commented 4 years ago

Hey there, it looks like the event.target of the onconnected/ondisconnected events changes to the last emitted event when using async event handlers.

Codepen: https://codepen.io/jaschaio/pen/NWWevNN?editors=0010

Code Example:

const { Component, bind } = hyperHTML;

const timeout = ( ms ) => {
    return new Promise( ( resolve ) => setTimeout( resolve, ms ) );
}

class Second extends Component {

  async onconnected( event ) {
    await timeout( 1000 );
    console.log( "connected Second Component", event.target );
  }

  render() {
    return this.html`<div onconnected=${ this }>Second Component</div>`
  }

}

class First extends Component {

  async onconnected( event ) {
    await timeout( 2000 );
    console.log( "connected First Component", event.target );
  }

  render() {
    return this.html`<div onconnected=${ this }>First Component</div>`
  }

}

class Container extends Component {

  render() {

    return this.html`<div>
      ${ First.for( this ) }
      ${ Second.for( this ) }
    </div>`

  }

}

bind( document.body )`${ Container.for( document.body ) }`;

I would expect the Following console.log output:

connected Second Component <div>Second Component</div>
connected First Component <div>First Component</div>

but I actually always get the Second Component div as the event.target:

image

WebReflection commented 4 years ago

It's currentTarget, not target ... target can be any node, currentTarget is the one where you attached the event.

That being said, I am not planning to rewrite the native event bus, so if currentTarget doesn't solve, you should find a better solution, as I don't think I can do much, it's all native behaviour you can replicate without the lib, hence expected.

P.S. of course unless it's not a bug of disconnected library

jaschaio commented 4 years ago

Thanks for your input. event.currentTarget is actually null when awaiting something.

But it works both with event.target and event.currentTarget when storing it to another variable before calling await:

  async onconnected( event ) {
    var target = event.target;
    await timeout( 1000 );
    console.log( "connected Second Component", target );
  }

As you said this is probably all native behaviour and has nothing to do with hyperhtml. I will leave it for reference in case somebody else runs into a similar issue.

WebReflection commented 4 years ago

I still suggest you use currentTarget, as it will always be the element with a listener, not one of its children.