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

Mic*_*hov 3 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)
Run Code Online (Sandbox Code Playgroud)

和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} />
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

这些只是在某些事件中调用通过道具传递的函数.

有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)的现代方法?

Jos*_*eau 5

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

你可以使用箭头功能:

<Destination
  onSelectSuggest={destination => (
    this.props.setDestination(destination, 'origin')
  )}
/>
Run Code Online (Sandbox Code Playgroud)

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

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

<Destination
  enterText={::this.enterText}
/>
Run Code Online (Sandbox Code Playgroud)

(显然,那个人需要babel)


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

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

  render() {
    return <Destination enterText={this.enterText} />
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

也就是说,无论哪种方式都没关系.在成为问题之前,不要过分担心性能; 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}
      />
    )
  }
}
Run Code Online (Sandbox Code Playgroud)