ReactJS以正确的方式绑定组件方法

时间:2016-01-09 16:13:59

标签: javascript reactjs

我在组件中使用方法时尝试使用.bind()。 原因很简单:在一个循环中,我正在修复组件并使用调用方法的属性扩展它们。但是对于每个循环项,我想用一些信息(比如一个密钥)扩展this对象。

示例:

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(...);

在这种情况下(及其工作)当Item Component触发prop&#34; eventMethodInItem&#34;我的方法&#34; eventMethod&#34;将被调用,this.key具有正确的值!

那么 - 现在问题是什么?它的工作完美,对吧?

但是ReactJS不希望我这样做。这就是ReactJS告诉我的控制台日志。

警告:bind():您正在将组件方法绑定到组件。 React会以高性能方式自动为您执行此操作,因此您可以安全地删除此调用。请参阅项目

也许你认为它是一个&#34;坏&#34;像我一样在组件中添加子项的方法但在我的特殊情况下我需要以这种方式执行此操作 - 所以我需要将新信息绑定到方法。

3 个答案:

答案 0 :(得分:4)

我不会假装我明白你在这里想做什么,但也许我可以帮忙清理它。

React采用每个组件上的所有顶级方法,并自动将它们绑定到组件的上下文。

这可以防止其他方法覆盖this的上下文,因此,如果您尝试重新绑定该方法,React说&#34;嘿,不要打扰。我已经得到了它#34; - 这是你看到的警告。

假设您确实想要这样做(每次通过覆盖properties属性来改变外部eventMethodInItem对象时)。

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

然后,我无法看到eventMethod必须存在于组件上的任何原因,而不仅仅是items函数的范围。

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
    }));
    // ...
  });
},

这样你就不必为了让你的程序运转而与React作斗争。

答案 1 :(得分:2)

使用this http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation时,React已经自动绑定React.createClass

将绑定更改为

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

和您的eventMethod

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

我还建议使用_.map代替_.each

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

答案 2 :(得分:1)

良好的模式 https://www.newmediacampaigns.com/blog/refactoring-react-components-to-es6-classes

之前:

<h1 id="heading">Heading</h1> <h2 id="sub-heading">Sub-heading</h2> <h3 id="another-deeper-heading">Another deeper heading</h3> <p>Paragraphs are separated by a blank line.</p> <p>Leave 2 spaces at the end of a line to do a<br>line break</p> <p>Text attributes <em>italic</em>, <strong>bold</strong>, <code>monospace</code>, <del>strikethrough</del> .</p> <p>Shopping list:</p> <ul> <li>apples</li> <li>oranges</li> <li><p>pears Numbered list:</p> </li> <li><p>apples</p> </li> <li>oranges</li> <li>pears</li> </ul> <p>The rain---not the reign---in Spain.</p> 

之后:

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

这个主题的另一个好的黑客http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html