Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Bind callback methods at TriadJS

Bind callback methods at TriadJS

Mark Pedrotti

August 10, 2017
Tweet

More Decks by Mark Pedrotti

Other Decks in Programming

Transcript

  1. Painful problem For a non-arrow function,
 the value of this

    when it is called
 depends on how it is called.
  2. depends on how it is called: • constructor new F

    or new F(…) • bound f.bind(context)(…) • apply or call f.apply or f.call(context, …) • method context.f(…) • function f(…)
  3. A tale of two functions “It was the best of

    times, it was the worst of times…” for the Review Deck button in my fork of Zebreto from Learning React Native
  4. class NewCard extends React.Component { _reviewDeck() { this.props.reviewDeck(this.props.deckID); } _reviewDisabled()

    { return this.props.noCardsDue; } render() { return <Button onPress={this._reviewDeck} disabled={this._reviewDisabled()}> <InterfaceText>Review Deck</InterfaceText> </Button>; } } What about the invocations?
  5. class NewCard extends React.Component { _reviewDeck() { this.props.reviewDeck(this.props.deckID); } _reviewDisabled()

    { return this.props.noCardsDue; } render() { return <Button onPress={this._reviewDeck} disabled={this._reviewDisabled()}> <InterfaceText>Review Deck</InterfaceText> </Button>; } } Here is a method invocation:
  6. class NewCard extends React.Component { _reviewDeck() { this.props.reviewDeck(this.props.deckID); } _reviewDisabled()

    { return this.props.noCardsDue; } render() { return <Button onPress={this._reviewDeck} // callback: no parens disabled={this._reviewDisabled()}> <InterfaceText>Review Deck</InterfaceText> </Button>; } } Is this an invocation? No, it’s a function
  7. The caller of the callback function 
 makes a function

    invocation f(…)
 not a method invocation context.f(…) The references to this don’t work: • undefined in strict mode • global or window otherwise
  8. “Be careful about this in JSX callbacks. 
 If you

    refer to a method without () after it, 
 bind that method. This is not React-specific; 
 it is how functions work in JavaScript.” https://facebook.github.io/react/docs/handling-events.html
  9. Simple solution For an arrow function,
 the value of this

    when it is called
 depends on where it is declared. Lexical this = consistent value of this Its context can’t change 

  10. Patterns to bind callback methods // 1. React.createClass binds methods

    // 2. Bind callback function in render method // 3. Use arrow function in render method // 4. Bind callback function in constructor // 5. Define callback arrow function in constructor // 6. Declare arrow function as a class property
  11. // 1. React.createClass binds methods: it isn’t the future of

    React var NewCard = React.createClass({ _reviewDeck: function () { this.props.reviewDeck(this.props.deckID); // does need bind :) }, _reviewDisabled: function () { return this.props.noCardsDue; // doesn’t need bind :( }, render: function () { return /* Button */; } });
  12. // 2. Bind callback function in render method: be aware

    of perf class NewCard extends React.Component { _reviewDeck() { this.props.reviewDeck(this.props.deckID); } _reviewDisabled() { return this.props.noCardsDue; } render() { return <Button onPress={this._reviewDeck.bind(this)} disabled={this._reviewDisabled()}> <InterfaceText>Review Deck</InterfaceText> </Button>; } }
  13. // 3. Use arrow function in render method: be aware

    of perf class NewCard extends React.Component { _reviewDeck() { this.props.reviewDeck(this.props.deckID); } _reviewDisabled() { return this.props.noCardsDue; } render() { return <Button onPress={() => { this._reviewDeck(); }} disabled={this._reviewDisabled()}> <InterfaceText>Review Deck</InterfaceText> </Button>; } }
  14. // 4. Bind callback function in constructor: requires repetition class

    NewCard extends React.Component { constructor(props) { super(props); // property of instance = bound property of prototype this._reviewDeck = this._reviewDeck.bind(this); } _reviewDeck() { this.props.reviewDeck(this.props.deckID); } _reviewDisabled() { return this.props.noCardsDue; } render: function () { return /* Button */; } }
  15. // 5. Define callback arrow function in constructor: different place

    class NewCard extends React.Component { constructor(props) { super(props); this._reviewDeck = () => { this.props.reviewDeck(this.props.deckID); }; } _reviewDisabled() { return this.props.noCardsDue; } render: function () { return /* Button */; } }
  16. // 6. Declare arrow function as a class property: not

    (yet) standard class NewCard extends React.Component { _reviewDeck = () => { this.props.reviewDeck(this.props.deckID); } _reviewDisabled() { return this.props.noCardsDue; } render: function () { return /* Button */; } }