1

I'm including this Stack Overflow thread since I've been relying on it heavily for this situation, but I'm not quite sure how to get the syntax right for my case.

Of the multiple solutions provided in that thread, here's one example of how to make an onClick with multiple functions:

<a href="#" onClick={(event) => { func1(); func2();}}>Test Link</a>

Trying to apply this situation of an onClick with multiple functions to my code, I have this:

<span className={mobileMenuClass.join(' ')} 
        onClick={(event) => {this.toggle.bind(this); this.togglePopup.bind(this)}}>
    <span id="menu-rect-top"></span>
    <span id="menu-rect-middle"></span>
    <span id="menu-rect-bottom"></span>
</span>

This doesn't cause any errors, but neither of the two functions fire.

I first had the onClick written with one function, like this:

onClick={this.toggle.bind(this)}

...which did work, but once I added the second function, both no longer worked. Trying this with the other function...

onClick={this.togglePopup.bind(this)}

...also works as expected.

I think I can give this onClick a single handleClick function, like this:

onClick={handleClick()}

...but also not sure how to work with these two binds that are needed for these functions.

rpivovar
  • 3,150
  • 13
  • 41
  • 79
  • 2
    The issue you are experiencing is a vanilla javascript issue. You should read up on how functions are invoked, what `.bind` does and how event listeners / callbacks are applied ... etc. Also as a side note, its generally better to create the handler function on the class itself (instead of an inline lambda) so you only allocate memory/one function reference for it once – John Ruddell Mar 10 '19 at 22:14
  • Yeah, I've only read a little bit about `bind` -- I understand what it's doing with `this`, but I overlooked its difference between `call`, which, if I'm understanding right, will fire the function vs `bind` which returns a function? Aaah..still confusing to me. I have to read more on it. Thanks for your comment. – rpivovar Mar 10 '19 at 22:26
  • 1
    No worries! thats what SO is for :) So think about `bind` and what it would be doing. You want to bind something onto a function.. Its used for a lot of different purposes, most popular would be to change the `this` context of a function.. it can also be used to bind additional arguments to that function though. `this.toggle.bind(this, 'some string arg')` for instance :) – John Ruddell Mar 10 '19 at 22:33

1 Answers1

2

onClick={handleClick()} is incorrect way to pass a handler because handleClick is called immediately and presumably returns undefined instead of a function.

It's safe to assume that toggle and togglePopup are class prototype methods that weren't bound:

class Comp extends Component {
  toggle() { ... }
  togglePopup() { ... }
  ...
}

Functions don't fire because they aren't called:

onClick={(event) => {this.toggle.bind(this); this.togglePopup.bind(this)}}

this.toggle.bind(this) binds a function and returns bound function. It doesn't call a function. It's necessary to bind a function only if it's passed as a callback and will be called with wrong context. While these functions aren't passed as callbacks but called with correct this context in-place so they don't need to be bound:

onClick={(event) => {this.toggle(); this.togglePopup()}}
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • 1
    You may want to correct the way you worded this. `While these functions are called with correct context and don't need to be bound`. This is inaccurate in the sense that the class context isn't bound on those functions unless explicitly bound by the developer (aka `this.props` would be undefined) – John Ruddell Mar 10 '19 at 22:18
  • @estus great answer. I am just barely learning about `bind` and `call`...will have to continue reading up on these. Your solution is pretty straightforward. I guess I was intimidated by the initial syntax I had `this.toggle.bind(this)` (which I admittedly had taken from another example elsewhere). Thanks for your answer – rpivovar Mar 10 '19 at 22:23
  • 1
    @JohnRuddell *This is inaccurate in the sense that the class context isn't bound on those functions unless explicitly bound by the developer* - yes, this is what I meant. Thanks for the suggestion, but I'm not sure how this can be stated more clearly. It's safe to assume that `toggle` is not bound, i.e. it's regular class proto method. If it were called with wrong context like `this.toggle.call(null)` it would misbehave. – Estus Flask Mar 10 '19 at 22:24
  • @rpivovar You're welcome. You may want to use arrow methods most times in React but `bind` is generally more beneficial, see https://stackoverflow.com/a/45882417/3731501 – Estus Flask Mar 10 '19 at 22:25
  • For sure, I get what you meant by it... but for newer developers the misconception could be that they have the class context bound. I would just add the clarification that you're assuming both `toggle` and `togglePopup` are pre-bound to the class. :) Regardless tho, got a vote from me! – John Ruddell Mar 10 '19 at 22:27
  • @JohnRuddell Thanks. I added a clarification that there's an assumption that the methods aren't bound. – Estus Flask Mar 11 '19 at 10:19