【问题标题】:How do I keep context in react without stringing .bind(this)?如何在不串接 .bind(this) 的情况下保持上下文反应?
【发布时间】:2016-03-12 09:20:04
【问题描述】:

我正在使用 react 从解析中检索数据,在我自己的函数中对其进行操作,然后在渲染中更新组件。

问题是我无法在我自己的复杂函数中更新状态,除非我附加一个 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) 吗?

【问题讨论】:

  • 为什么不使用局部变量呢?

标签: parse-platform reactjs


【解决方案1】:

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

使用 ES6 箭头

如果你使用 ES6 箭头来定义你的函数。箭头函数强制 this 的内部上下文与外部上下文相同,无论函数如何调用。

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

创建对 this 的引用并使用 that。

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

【讨论】:

  • 好的,所以 Tyrsius 引用了您上面的第三个选项?
  • 没错。不过我不太喜欢这个选项,总感觉有点老套。
  • 他特别说他没有使用 ES6,并且“作为参数”会产生相同的字符串结尾 this
  • @Tyrsius 好的,也许它会帮助别人?我只是列出备选方案,而不是试图猜测提问者想要使用哪一个。
  • 感谢您的所有回答。我不能投票,因为我是一个口香糖。
【解决方案2】:

在函数开头使用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);
     });
  });
}

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      使用 ES7 属性初始化器语法,目前在 Babel 中实现。 关键是methodName = () =&gt; { //method return } 你可以阅读更多here

      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
          })
        }
      }

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

      【讨论】:

        猜你喜欢
        • 2021-07-04
        • 2023-03-21
        • 1970-01-01
        • 1970-01-01
        • 2022-01-07
        • 2012-04-07
        • 2021-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多