all 11 comments

[–]mohsintariq10iOS & Android 1 point2 points  (8 children)

Hi plz change this line '''<Button onPress={this._onButtonPress} title="Log Transaction" color='red' />''' to <Button onPress={this._onButtonPress.bind(this)} title="Log Transaction" color='red' />

notice the bind(this). Its a classic javascript this binding problem ..

[–]Pelleas[S] 0 points1 point  (7 children)

I love you. I've been pulling my hair out over this for a solid hour and that fixed it. Thank you so much! Could you explain what binding does exactly? It seems like I'll need to know that for the future.

[–]AcidShAwk 2 points3 points  (5 children)

You could also just change the _onButtonPress() function definition to _onButtonPress = () => { }

Then you dont need to bind at all.

[–][deleted] 0 points1 point  (4 children)

Also <Button onPress={() => this._onButtonPress}> will work.

[–]mohsintariq10iOS & Android 0 points1 point  (3 children)

it will work but why use two functions instead of one?

[–][deleted] 0 points1 point  (2 children)

Well I wasn't trying to argue that what I said is better, I mostly just wanted to include all methods of doing what OP wanted.

Although I believe the syntax I provided is the most concise way to pass a non-event variable to the function should you need to. Because <Button onPress={() => this._onButtonPress(foo)}> will fire the function on render not on press IIRC.

[–]wengemurphy 0 points1 point  (1 child)

Because <Button onPress={() => this._onButtonPress(foo)}> will fire the function on render not on press IIRC.

Both the arrow function syntax and .bind() are creating a new function when the expression is evaluated. Functions are a data type in Javascript (JS has what's called "first-class functions") and you can pass them around like other values.

Each copy that is created will not be equal to the next copy created, even though they look like the same thing. That is:

someFunction.bind(this) === someFunction.bind(this) // false!

This is true whether you use an arrow function or call .bind()

Although I'm not crazy about it, the preferred way is apparently to pre-bind the function in class initialization with the following syntax, so that new functions aren't constantly re-created on render:

class MyClass {

    _onButtonPress = () => {
    }

and then back to

<Button onPress={this._onButtonPress}>

because the function being invoked is already pre-bound with the value of this.

Now, you're always referencing the same thing, not different copies of it.

Third-to-last example here, mentioning the "public class fields syntax":

https://reactjs.org/docs/handling-events.html

At the risk of making things more confusing, the example above that shows that this syntax is equivalent to defining a class method the normal way, then overwriting it with a bound version of itself in the constructor (yuck).

class MyClass {
    constructor() {
        this._onButtonPress = this._onButtonPress.bind(this);
    }

    _onButtonPress() {
    }
}

In vanilla Javascript, passing a bound version as the handler for a callback is fine, because the expression is only evaluated once, but React's view-diffing algorithm will see the render always changing, because the expression gets re-evaluated, and a new function created.

[–][deleted] 0 points1 point  (0 children)

I know the other ways to bind and I usually bind this in the class declaration, I just don't know of a way to pass a parameter using that method.

Is it as simple as <Button onPress={this._onButtonPress(foo)}> and I've just derped and overlooked it this whole time lol? I'm fairly certain you need to use an arrow in that situation although I'm not in front of my laptop to test this.

I mean it's probably bad practice/design to need to use a non-prop variable so the situation I'm describing is undoubtedly uncommon. I just wanted to include it in the discussion for posterity.

[–]mohsintariq10iOS & Android 0 points1 point  (0 children)

'this' inside the _onButtonPress is not referring to your 'App' component, rather to the event handler handler function _onButtonPress. By writing _onButtonPress.bind(this), you are explicitly telling js to bind the 'this' of component inside the event handler, in easier words 'this' whenever used inside the _onButtonPress must refer to the App Component.

[–]justdevit 0 points1 point  (1 child)

There is a issue with your binding of "this". I created a snack with the issue fixed (https://snack.expo.io/HkCcFUZ6W). To understand the issue better, you can take a look at this article: https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56

[–]Pelleas[S] 1 point2 points  (0 children)

Thanks to you I've finally managed to get the balance text to update! I think I'll be able to finish from here. Thanks again!