4

I have the following code/snippet;

class App extends React.Component {
  loginComponent = <button onClick={this.signUp}>Sign Up</button>;
  
  signUp = () => {
    alert("test");
  }

  render() {
    return(
      <div>
        {this.loginComponent}
      </div>    
    )
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
#root {
width: 50%;
height: 50vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

When signUp uses Arrow Syntax, the function doesn't execute. When I use regular syntax;

signUp() {
   alert("test);
}

It executes fine. Any idea as to what my problem is, here?

  • What are the contexts of these functions and `display` assignment. Is this inside a React class component? Some context would possibly help – Jayce444 Jan 10 '20 at 12:03
  • Arrow functions do not have this. If 'this' is accessed, it is taken from the outside, where the arrow function is defined. Detailed explanation here https://javascript.info/arrow-functions – mpgbk Jan 10 '20 at 12:03
  • 1
    The function should be **called** either way, despite the differences in `this` noted above. Please update your question with a [mcve] demonstrating the problem, ideally a **runnable** one using Stack Snippets (the `[<>]` toolbar button). Stack Snippets support React, including JSX; [here's how to do one](http://meta.stackoverflow.com/questions/338537/). – T.J. Crowder Jan 10 '20 at 12:04
  • You haven't shown any declarations for `display` or (in the first code block) `renderSignUpForm`. They **are** declared, right? Because if not, that code is falling prey to what I all [*The Horror of Implicit Globals*](http://blog.niftysnippets.org/2008/03/horror-of-implicit-globals.html), which could be a factor... – T.J. Crowder Jan 10 '20 at 12:05
  • @Federico klez Culloca et. al. - there's no reason to believe this question is related to the `this` difference. – T.J. Crowder Jan 10 '20 at 12:06
  • @ Kwxhvor - If you update your question with an [MCVE](http://meta.stackoverflow.com/questions/338537/), I can reopen it if the problem isn't `this` (which I doubt it is). (Or point you at a more appropriate dupetarget.) – T.J. Crowder Jan 10 '20 at 12:08
  • Will do. Give me a second. –  Jan 10 '20 at 12:09
  • Updated as Requested @T.J.Crowder –  Jan 10 '20 at 12:37

1 Answers1

3

The problem is that you're defining your properties in the wrong order. When you define loginComponent, the value of this.signUp is undefined.

Reverse the order so signUp is initialized first:

class App extends React.Component {
  signUp = () => {
    alert("test");
  };

  loginComponent = <button onClick={this.signUp}>Sign Up</button>;
  
  render() {
    return(
      <div>
        {this.loginComponent}
      </div>    
    )
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
#root {
width: 50%;
height: 50vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

(Also note the ; at the end of the signUp assignment. ASI will add it for you, but it should be there if you aren't intentionally relying on ASI.)

Remember that with class fields, public property definitions are handled in order during instance creation, roughly as though you had this:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.signUp = () => {
      alert("test");
    };

    this.loginComponent = <button onClick={this.signUp}>Sign Up</button>;
  }

  render() {
    // ...
  }
}

It worked with the method definition because methods are defined when the prototype is created (when the class declaration is processed), which is before instance initialization.

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • That worked perfectly, thank you. Why was this only an issue with Arrow Syntax, and not with regular syntax? –  Jan 10 '20 at 12:43
  • 1
    @Kwxhvor - Hit refresh, I'd just added a note explaining that when you commented. :-) – T.J. Crowder Jan 10 '20 at 12:45
  • 1
    @Kwxhvor the problem is not about the arrow syntax, if you store a "normal" function in a class property, it will do the same. It is about hoisting here. – sjahan Jan 10 '20 at 12:45
  • 1
    Great, Thank you @T.J.Crowder –  Jan 10 '20 at 12:46