3

I am trying to use .bind() when using a method in my component. The reason is simple: In a loop I am returing Components and extend them with a property which is calling a method. But for every loop-item this I want to extend the this Object with some information (like a key).

Example:

Items.jsx

Items = React.createClass({
  eventMethod() {
    console.log('this event was triggered by key:', this.key);
  },
  items() {
    let items = [];
    let properties = {};
    _.each(this.props.items, (itemData, key)=>{
      properties.eventMethodInItem = this.eventMethod.bind(_.extend(this, {
        key
      }));
      let {...props} = properties;
      let item = <Item {...props} key={key} />;
      items.push(item);
    });
    return items;
  },
  render() {
    return(<div>{this.items()}</div>);
  }
});

Item.jsx

Item = React.createClass(...);

In this case (and its working) when the Item Component is triggering the prop "eventMethodInItem" my method "eventMethod" will be called and this.key has the correct value!

So - whats now the question ? Its working perfect, right ?

Yes.

But ReactJS does not want me to do this. This is what ReactJS is telling me as a console log.

Warning: bind(): You are binding a component method to the component. React does this for you automatically in a high-performance way, so you can safely remove this call. See Items

Maybe you think its a "bad" way to add children to the component like I am doing it but in my special case I need to do this in this way - so I need to bind new information to a method.

3 Answers 3

4

I'm not going to pretend that I understand what you are trying to do here, but maybe I can help clear it up anyway.

React takes all of the top level methods found on each component and automagically binds them to the context of the component.

This prevents other methods from overriding the context of this and as a result, if you try to rebind the method, React says "Hey don't bother. I already got it" — which is the warning you are seeing.

Assuming that you really want do this (each time you are mutating the outer properties object by overriding the eventMethodInItem property).

properties.eventMethodInItem = this.eventMethod.bind(_.extend(this, {
  key
}));

Then I can't see any reason that the eventMethod has to live on the component, rather than just in the scope of the items function.

items() {
  const eventMethod = function() {
    console.log('this event was triggered by key:', this.key);
  }
  // ...
  _.each(this.props.items, (itemData, key)=>{
    properties.eventMethodInItem = eventMethod.bind(_.extend(this, {
      key
    }));
    // ...
  });
},

That way you don't have to fight React to get your program to work.

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

2 Comments

You're right: In my case I don't have to use a component method. Thanks for this great idea. I did not think about that obvious solution!
Just for fun: What about the fact when I have to use a Component Method but also want to extend the binded Object ?
2

React is already autobinding this when using React.createClass http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation

Change your binding to

properties.eventMethodInItem = this.eventMethod.bind(null,key);

and your eventMethod to

eventMethod(key) {
    console.log('this event was triggered by key:', key);
}

I also suggest using _.map instead of _.each

items() {
  return _.map(this.props.items, (itemData, key) => {
    return <Item
          handleEventMethod={this.eventMethod.bind(null,key)}
          key={key} />;
  });
},

1 Comment

Binding the context to null is going to have the same effect and I think the asker wants to know why React doesn't want you to call .bind on component methods.
1

Good pattern https://www.newmediacampaigns.com/blog/refactoring-react-components-to-es6-classes

Before :

class ExampleComponent extends React.Component {
 constructor() {
  super();
  this. _handleClick = this. _handleClick.bind(this);
  this. _handleFoo = this. _handleFoo.bind(this);
 }
 // ...
}

After :

class BaseComponent extends React.Component {
 _bind(...methods) {
  methods.forEach( (method) => this[method] = this[method].bind(this) );
 }
}

class ExampleComponent extends BaseComponent {
 constructor() {
  super();
  this._bind('_handleClick', '_handleFoo');
 }
 // ...
}

another good hacks for this topic http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html

Comments

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.