React-hot-loader: Investigate what it would take to support function properties

Created on 18 Apr 2016  路  9Comments  路  Source: gaearon/react-hot-loader

e.g.

class App extends Component {
  handleClick = () => {
    this.setState(...)
  }
}

One way to approach this would be to hoist the bodies of the function properties into hidden methods on the prototype with mangled names. This would be unobservable to the user but make them available for react-proxy to see and hot reload.

enhancement help wanted

Most helpful comment

Yeah I get it, but if Babel is able to compile arrow functions correctly, so can we 馃槃 . Just a matter of having enough tests.

All 9 comments

hoist the bodies of the function properties into hidden methods on the prototype with mangled names

can you do that without a babel plugin?

I don鈥檛 think so. But then again, you can鈥檛 have class properties without Babel anyway?

yeah but then aren't we back to needing to identify classes that look like react components at compile time?

No, this transform is harmless for any class. I just mean turning

class Stuff {
  doSomething = (e) => {
    this.x(e.stuff())
  }
}

into

class Stuff {
  doSomething = (e) => {
    return this.___doSomethingqwertyu234567(e);
  },
  ___doSomethingqwertyu234567(e) {
    this.x(e.stuff())
  }
}

I鈥檓 not sure if there is anything in the spec that would make it a bad idea but it鈥檚 worth giving it a shot. The only special case I see so far is arguments object which should still end up being the one in constructor. To be honest we can bail completely when we see arguments used.

Hmm, I see, we might hit some edge cases related to the differences between regular functions and arrow functions, so we should bail out on use of super, new.target, and arguments as you said, and we also need to convert arrow functions without curly braces to regular functions with body

class Stuff {
  doSomething = (e) => this.x(e.stuff())
}
class Stuff {
  doSomething = (e) => {
    return this.___doSomethingqwertyu234567(e);
  },
  ___doSomethingqwertyu234567(e) {
    return this.x(e.stuff())
  }
}

so maybe it might be better to translate it to

class Stuff {
  doSomething = (e) => {
    return this.___doSomethingqwertyu234567(e);
  },
  ___doSomethingqwertyu234567(e) {
    return ((e) => this.x(e.stuff()))(e)
  }
}

this way the function would still be an arrow function... on the other hand we're creating a function on every invocation...

We need to create it once, otherwise it鈥檚 slow.

I鈥檓 not really sure I see your point about functions without body. We can just convert them to arrow functions without body that call those hidden methods. Or we can bail out because most event handlers are more than one liners, and commonly React code uses those just for event handlers. Handling majority of cases is good enough here.

yeah you're right, this doesn't need to work for everything.
I guess I'm just afraid of anything that changes code behaviour between development (where you'd use react hot loader, and class properties would be converted in this fashion) and production where you don't use it, especially if it changes the behaviour in subtle ways, like the differences between an arrow function and a regular function.

Yeah I get it, but if Babel is able to compile arrow functions correctly, so can we 馃槃 . Just a matter of having enough tests.

Added by #322, and out in 3.0.0-beta.4, thanks @nfcampos!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

niba picture niba  路  4Comments

lemonmade picture lemonmade  路  3Comments

mtscout6 picture mtscout6  路  3Comments

Opty1712 picture Opty1712  路  4Comments