19

How to fix this error when I have the binding this way: previously binding in constructor solved but this is a bit complex for me:

{this.onClick.bind(this, 'someString')}>

and

<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
monkeyjs
  • 604
  • 2
  • 7
  • 29

3 Answers3

44

Option 1:

Use arrow functions (with babel-plugins) PS:- Experimental feature

class MyComponent extends Component {
   handleClick = (args) => () => {
      // access args here;
      // handle the click event
   }

   render() {
     return (
       <div onClick={this.handleClick(args)}>
         .....
       </div>
     )
   }
 }

Option 2: Not recommended

Define arrow functions in render

   class MyComponent extends Component {
       render() {
         const handleClick = () => {
          // handle the click event
         }
         return (
           <div onClick={handleClick}>
             .....
           </div>
         )
       }
     }

Option 3:

Use binding in constructor

   class MyComponent extends Component {
       constructor() {
         super();
         this.handleClick = this.handleClick.bind(this);
       }

       handleClick() {
          // handle click
       }

       render() {

         return (
           <div onClick={this.handleClick}>
             .....
           </div>
         )
       }
     }
anoop
  • 3,229
  • 23
  • 35
8

I recommend you to use binding in the class constructor. This will avoid inline repetition (and confusion) and will execute the "bind" only once (when component is initiated).

Here's an example how you can achieve cleaner JSX in your use-case:

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

        // Bind functions
        this.handleClick = this.handleClick.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleClick() {
        this.onClick('someString');
    }
    onClick(param) {
        // That's your 'onClick' function
        // param = 'someString'
    }

    handleSubmit() {
        // Same here.
        this.handleFormSubmit();
    }
    handleFormSubmit() {
        // That's your 'handleFormSubmit' function
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <p>...</p>
                <button onClick={this.handleClick} type="button">Cancel</button>
                <button type="submit">Go!</button>
            </form>
        );
    }
}
Graham
  • 7,431
  • 18
  • 59
  • 84
Kaloyan Kosev
  • 12,483
  • 8
  • 59
  • 90
  • This does not work - infinite loop - bundle.js:10623 Warning: setState(...): Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state. – monkeyjs Nov 24 '16 at 20:50
  • Hey @monkeyjs , I just updated my answer with a code example for your use-case. Please try this way. If you again receive the same error, the issue is somewhere else. Then please share more complete code example and I'll try to help you. – Kaloyan Kosev Nov 24 '16 at 22:29
2

Even though all the previous answers can achieve the desire result, but I think the snippet below worth mentioning.

class myComponent extends PureComponent {

  handleOnclickWithArgs = arg => {...};

  handleOnclickWithoutArgs = () => {...};

  render() {
    const submitArg = () => this.handleOnclickWithArgs(arg);
    const btnProps = { onClick: submitArg }; // or onClick={submitArg} will do

    return (
      <Fragment>
        <button {...btnProps}>button with argument</button>
        <button onClick={this.handleOnclickWithoutArgs}>
          button without argument
        </button>
     </Fragment>
   );
  }
}