ractivejs / ractive

Next-generation DOM manipulation
http://ractive.js.org
MIT License
5.94k stars 396 forks source link

Breaking error while removing a decorator on component's render #3241

Closed giovannipiller closed 6 years ago

giovannipiller commented 6 years ago

Description:

Removing an element (with a decorator) on component's render, triggers a JS error.

Error is in Decorator.js's render function

let args;
if (this.fn) {
  args = this.models.map(model => {

this.models is null.

Versions affected:

Interestingly, 0.8.x doesn't seem to be affected.

Platforms affected:

Tested on Chrome & Safari.

Reproduction:

JSFiddle.

const r = window.r = new Ractive({
  el: '#main',
  template: `
  <h1>Open the console to see the error</h1>
  <p>My Decorator must at least have ="", or any parameter, to reproduce issue.</p>
  {{#if showDecoratedDiv}}
    <div as-myDecorator=""></div>
  {{/if}}
  `,
  decorators: {
    myDecorator() {
      console.info('decorated')
      return {
        teardown() {
          console.info('teardown')
        }
      }
    }
  },
  data: {
    showDecoratedDiv: true,
  },
  onrender() {
    this.toggle('showDecoratedDiv');
  }
});

Interestingly, applying a decorator without any argument whatsoever, will not thrown an error:

{{#if showDecoratedDiv}}
  <div as-myDecorator>gino</div>
{{/if}}
dagnelies commented 6 years ago

It also appears to be related to the fact that it's called in onrender. It works fine in oninit and outside too.

With all the lifecycle hooks, it's also not very easy to know which one "should" be used in what situation.

evs-chris commented 6 years ago

When travis finishes travising, decorators that try to init with an unrendered host element will just bail instead of possibly dying on edge and v0.10-dev. Thanks for the report!

giovannipiller commented 6 years ago

Thanks Chris! :)

Would it be possible to back-port it to 0.9.x? (I'm going to manually include the fix for now, but it could be useful to others too)

giovannipiller commented 6 years ago

It also appears to be related to the fact that it's called in onrender. It works fine in oninit and outside too

Yup. For context: in our app, this happened during the re-computation of a computed property, among other things.