Shawn Chen
Shawn Chen

Reputation: 1097

why <button onClick={this.props.onClick}> is different from <button onClick={(e) => {this.props.onClick(e)}}> here?

I found the following code in this post.(sandbox) I am not sure why these buttons behave differently.

One possible explanation is: Because Button's render method is not invoked for updating, the first button's click handler remains the same. However, this.props of the Button instance has changed to include the new onClick prop. In other words,if the props of a component element is changed, nextProps will finally become this.props even when shouldComponentUpdate returns false.

const submit = val => alert(val);
class App extends React.Component {


state = { val: "one" }

  componentDidMount() {
    this.setState({ val: "two" })
  }

  render() {
    return <Form value={this.state.val} />
  }
}

const Form = props => (
  <Button
    onClick={() => {
      submit(props.value)
    }}
  />
)

class Button extends React.Component {
  shouldComponentUpdate() {
    // lets pretend like we compared everything but functions
    return false
  }

  handleClick = () => this.props.onClick()

  render() {
    return (
      <div>
        <button onClick={this.props.onClick}>This one is stale</button>
        <button onClick={() => this.props.onClick()}>This one works</button>
        <button onClick={this.handleClick}>This one works too</button>
      </div>
    )
  }
}

Upvotes: 0

Views: 7046

Answers (2)

Claire Lin
Claire Lin

Reputation: 2382

Your explanation is correct on that when ShouldComponentUpdate() returns false, the Button component does not re-render on props change.

In the first <button> element, the onClick event is this.props.OnClick which is actually the function () => { submit("one"); } at the moment of the initial rendering. "one" is here because at this particular time point in the React lifecycle, Form's props.value evaluates to "one". Note that the function gets executed has nothing to do with Button's props.

In the second <button> element, however, the onClick event is () => this.props.onClick(). Regardless whether the Button component gets re-rendered, it is always the this.props.onClick() that get executed, where this.props changes when the parent components get state/props updates.

In the case of ShouldComponentUpdate() returning true, Button component will re-render on props updates. The first button's onClick event becomes a new function () => { submit("two"); } on the re-render triggered by the App component's state change. The two button elements' onClick event functions are never the same function, although they appear to produce the same result.

Upvotes: 1

Treycos
Treycos

Reputation: 7492

<button onClick={this.props.onClick}> Will call your onClick function and send an event object as its first parameter. This is the equivalent of doing this :

<button onClick={event => { this.props.onClick(event) }}>

<button onClick={() => this.props.onClick()}> Will set what your onClick function returns as the onClick function... It is the short syntax of the following code :

<button onClick={() => { return this.props.onClick() }}>

What you may be looking for is this : <button onClick={() => { this.props.onClick() }}>

In this case, clicking will simply call your function without sending any arguments

I suggest reading this documentation to know more about arrow/anonymous functions and their syntax

Upvotes: 0

Related Questions