如何避免使用组件(ES6类)在react / redux容器中绑定

时间:2016-07-03 10:13:07

标签: reactjs redux

我有简单的react / redux app和带有两个目标自动选择组件的搜索表单的容器:

class QuoteBox extends Component {
    onSelectSuggest(target, destination) {
        this.props.setDestination(destination, target);
    }

    render() {
        return (
            <Destination
                    direction="From"
                    key="dest-from"
                    enterText={this.props.enterText.bind(this)}
                    onSelectSuggest={this.onSelectSuggest.bind(this, "origin")}
                    dataSource={this.props.originSuggests} />

            <Destination
                    direction="To"
                    key="dest-to"
                    enterText={this.props.enterText.bind(this)}
                    onSelectSuggest={this.onSelectSuggest.bind(this, "destination")}
                    dataSource={this.props.destinationSuggests} />
        )
    }
}

function mapStateToProps(state) {
    return {
        originSuggests: state.originSuggests,
        destinationSuggests: state.destinationSuggests,
        origin: state.origin,
        destination: state.destination
    }
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        enterText: enterText,
        setDestination: setDestination
    }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps )(QuoteBox)

和Destination是一个简单的组件,如

export default class Destination extends Component {
    render() {
        return (
            <AutoComplete
                    onUpdateInput = { _.debounce((term) => {
                        this.props.enterText(term);
                        this.setState({
                            searchText: term
                        })
                    }, 300) }
                    onNewRequest = {(x) =>{this.props.onSelectSuggest(x)}}
                    dataSource={this.props.dataSource} />
        )
    }
}

在一些事件中只调用通过道具传递的函数。

有autobind功能但在ES6课程中不可用:https://medium.com/@goatslacker/react-0-13-x-and-autobinding-b4906189425d#.nkv1cn32v 我看到很多变通办法 http://www.ian-thomas.net/autobinding-react-and-es6-classes/ 或第三方图书馆。

在将容器中的方法传递给简单组件时,什么是避免这种绑定(this)的现代方法?

1 个答案:

答案 0 :(得分:5)

有许多现代方法,但它们都围绕着相同的想法:)

您可以使用箭头功能:

<Destination
  onSelectSuggest={destination => (
    this.props.setDestination(destination, 'origin')
  )}
/>

(我喜欢这个,因为我们放弃了论证 - 翻转onSelectSuggest方法!)

对于更简单的绑定,您可以使用ESNext绑定运算符(::):

<Destination
  enterText={::this.enterText}
/>

(显然,那个人需要巴贝尔)

编辑2017年9月27日:&#39; bind&#39;运营商似乎没有将其纳入规范;更现代的方法是使用属性初始化器语法(也是即将推出的JS功能,但我相信它更有可能使其成为语言):

class SomeComponent extends Component {
  enterText = () => {
    // body here
  }

  render() {
    return <Destination enterText={this.enterText} />
  }
}

最后,最有效的方法是在构造函数中进行绑定。

class QuoteBox extends Component {
  constructor(props) {
    super(props);
    this.enterText = this.props.enterText.bind(this);
  }
  render() {
    return (
      <Destination
        enterText={this.enterText}
      />
    )
  }
}

这更有效的原因是因为绑定非常慢,并且在您的示例中,它是在每个渲染上完成的。当它被初始化时,最好这样做一次。

那就是说,它可能并不重要。在成为问题之前,不要过分担心性能; React很快,除非你处理一个非常复杂的组件树,否则它可能是一个微不足道的差异。

同样,在AutoComplete中,您应该在构造函数中绑定debounced函数:

class Destination extends Component {
  constructor(props) {
    super(props);
    this.updateInput = _.debounce(this.updateInput, 300)

  updateInput(term) {
    this.props.enterText(term); 
    this.setState({
      searchText: term
    }) 
  }  

  render() {
    return (
      <AutoComplete
        onUpdateInput={this.updateInput}
        onNewRequest={this.props.onSelectSuggest}
      />
    )
  }
}