2

I'm trying to follow the suggestion in this react-eslint doc to avoid using inline functions.

I have a div with an onClick funciton like so:

onClick={ () => this.props.handleClick(some_constant) }

This works perfectly fine, however I don't want to have an inline function. When I try to abstract it by following the pattern in the provided link above, I get a setState error that runs infinitely.

class Foo extends React.Component {
  constructor() {
    super();

    this._handleClickWrapper = this.handleClickWrapper.bind(this);
  }

  _handleClickWrapper() {
    // handleClick is a callback passed down from the parent component
    this.props.handleClick(some_constant)
  }

  render() {
    return (
      <div onClick={this._handleClickWrapper}>
        Hello!
      </div>
    );
  }
}

What needs to be done so that I can avoid using inline functions?

Edit:

I made a serious typo, but in my code, I have what is currently reflected and it is still causing the error.

6
  • 1
    I find that advice to be extremely hard to take seriously. Commented Feb 8, 2017 at 2:57
  • What "setState error that runs infinitely" do you get? I use the pattern you've presented all the time... Commented Feb 8, 2017 at 3:01
  • I don't really know React, but my first thought is that this doesn't work the same way in arrow functions as in traditional functions. Commented Feb 8, 2017 at 3:04
  • 1
    onClick={ this.props.handleClick.bind(this, some_constant) } ? Commented Feb 8, 2017 at 10:46
  • @pawel The correct answer Commented Feb 8, 2017 at 22:43

3 Answers 3

4

You bound the wrong function to this. It should be:

this._handleClickWrapper = this._handleClickWrapper.bind(this);

This way _handleClickWrapper will always be bound to the context of the component.

Sign up to request clarification or add additional context in comments.

2 Comments

I made a big mistake. Thanks for the catch, but that's not the cause of the issue.
How about passing props? constructor(props) and super(props)
1

If you really really really want to follow the jsx-no-bind rule, you can create a new component and pass someConstant in as a prop. Then the component can call your callback with the value of someConstant:

class FooDiv extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

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

  handleClick() {
    this.props.onClick(this.props.someConstant);
  }
}

Then your Foo component can just do this:

class Foo extends React.Component {
  render() {
    const someConstant = ...;
    return (
      <FooDiv
        onClick={this.props.handleClick}
        someConstant={someConstant}
      />
    );
  }
}

Having said that, I would recommend not following jsx-no-bind and just use bind or arrow functions in render. If you're worried about performance due to re-renderings caused by using inline functions, check out the reflective-bind library.

Comments

0
  1. There is a typo

this._handleClickWrapper = this.handleClickWrapper.bind(this);

should be

this._handleClickWrapper = this._handleClickWrapper.bind(this);

  1. in your constructor you forgot to pass props to super()

    constructor(props) {
      super(props);
      this._handleClickWrapper = this._handleClickWrapper.bind(this);
    }
    

Tipp: You can avoid binding (and even the constructor) by using arrow functions declaration inside the class (babel-preset-es2016).

class Foo extends React.Component {

  state = {} // if you need it..

  onClick = () => {
    this.props.handleClick(some_constant)
  }

  render() {
    return (
      <div onClick={this.onClick}>
        Hello!
      </div>
    );
  }
}

This way you components gets smaller, and easier to read.

https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding

2 Comments

es6 classes don't autobind
right, need to include babel-preset-es2016 facebook.github.io/react/blog/2015/01/27/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.