如何保持上下文的反应而不用字符串.bind(this)?

时间:2015-12-07 17:08:22

标签: parse-platform reactjs

我使用react从parse中检索数据,在我自己的函数中操作它,然后更新渲染中的组件。

问题是我无法在我自己的复杂函数中更新状态,除非我附加了一串bind(this)。整个组件如下所示:

React.Component({

getInitialState: function () {
 return{ 
  isloading:true
 }
},

componentDidMount: function(){
 this.myStupidFunction()
}, 

myStupidFunction : function(){
(
 (
  (nested parse queries that eventually ... 
 return an object and set isloading:false).bind(this))
.bind(this))
.bind(this)
},

render: function (){
  if (this.state.isloading) {
   return(
    <Text "...isloading"/>
   )
  } else {
   return(
    ...actually return important stuff...
   )
  }
 }
})

更聪明的方法是什么?我是否需要为每个嵌套函数真正.bind(this)?

4 个答案:

答案 0 :(得分:3)

有几种方法可以维护组件的上下文。

使用ES6箭头

如果使用ES6箭头定义功能。无论函数如何被调用,箭头函数都强制将其内部上下文与外部上下文相同。

parse.find({
  success: results => {
    // this is correct
    console.log(this);
  }
});

我认为这是最优雅的解决方案,但是not all browsers support arrow functions yet

使用组件方法

React会自动将this绑定到组件的每个顶级方法中。他们总是保证有正确的背景。

onSuccess: function() {
  // this is correct
  console.log(this);
},
componentWillMount: function() {
  parse.find({
    success: this.onSuccess
  });
}

在我看来,这也相当优雅。它让React在你编写代码时处理上下文的混乱。但是,这可能意味着您最终会在组件的顶层使用太多方法,因此请谨慎使用。

作为论据

某些函数(例如map)允许您可选地传递上下文以用作this作为最终参数。这使您可以在没有.bind(this)的情况下维护正确的上下文。

data.map(function() {
  console.log(this);
  // this is correct
}, this);

这仅适用于某些方法,因此它不是真正的通用解决方案。

别名this

创建对此的引用并改为使用它。

var __this__ = this;

parse.find({
  success: results => {
    // __this__ is correct
    console.log(__this__);
  }
});

这个hack在Javascript中一直存在,但我不认为这是解决问题的好方法。

使用ES7功能绑定

对于那些喜欢Javascript的人来说,你也可以使用ES7 function bind syntax proposal来实现这一目标 - 目前已在Babel中实施。

parse.find({
  success: this::function(results) {
    // this is correct
    console.log(this);
  }
});

这需要使用ES7的实验提案阶段功能。您可能不想开始使用它,但是要注意这一点非常有趣。左侧的值将绑定到右侧的函数中,如this

答案 1 :(得分:0)

在函数开头使用closure来捕获this。它可以在任何嵌套结构中使用。这种闭包的常规名称是self _thisthat。我更喜欢self

myStupidFunction : function(){
  var self = this;
  someAsyncCall(1,2, function(result) {
     //some nested stuff
     anotherAsyncCall(1,2 function(innerResult) {
       self.setState(innerResult);
     });
  });
}

答案 2 :(得分:0)

一个解决方案可能是使用局部变量

myStupidFunction:function(){
    var that=this
    ParseReact.Mutation.Create('Place', {
                    name: 'New Place',
                    user: Parse.User.current()
                })
                .dispatch()
                .then(function() {
                    that.refreshQueries();
                });
}

答案 3 :(得分:0)

使用ES7 Property Initalizer语法,目前在Babel中实现。 关键是methodName = () => { //method return } 您可以阅读更多here

&#13;
&#13;
import React from 'react';

export default class Note extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      editing : false
    }
  }

  render() {
    const editing = this.state.editing;
    return (
      <div>{ editing ? this.renderEdit() : this.renderTask() }</div>
    )
  }

  renderEdit = () => {
    return (
      <input type="text"
             className="edit-input"
             autoFocus={true}
             defaultValue={this.props.task}
             onBlur={this.finishEdit}
             onKeyPress={this.checkEnter} />
    )
  }

  renderTask = () => {
    const onDelete = this.props.onDelete;
    return (
      <div onClick={this.edit}>
        <span className="task-body">{this.props.task}</span>
        { onDelete ? this.renderDelete() : null }
      </div>
    )
  }

  renderDelete = () => {
    return (
      <button className="delete-btn" onClick={this.props.onDelete}>x</button>
    )
  }

  edit = () => {
    this.setState({
      editing : true
    })
  }

  checkEnter = (e) => {
    if(e.key === "Enter") {
      this.finishEdit(e);
    }
  }

  finishEdit = (e) => {
    this.props.onEdit(e.target.value);
    this.setState({
      editing : false
    })
  }
}
&#13;
&#13;
&#13;

//注意:上面项目中的示例类。