【问题标题】:How can I tell when this.setState exists in ES6?如何判断 this.setState 何时存在于 ES6 中?
【发布时间】:2017-05-22 20:06:51
【问题描述】:

我一直在努力尝试将我的 React 代码从 ES5 迁移到 ES6。正如我现在发现的那样,this 不再自动绑定,这会导致各种地狱。

我试图通过反复试验找出正在传递的对象。到目前为止,我可以找到所有内容并进行相应调整。但是,当涉及到 this.setState 时,我遇到了问题,因为它 在 console.log 中不可见!!!!查看 ES5 中的屏幕截图:

这是 ES6 中相同的代码:

请教我如何钓鱼,即帮助我弄清楚如何理解对象何时具有 this.setState?

我尝试过的事情

  1. 通过谷歌搜索,我了解到您可以通过更改基本组件来default bind everything。不幸的是,这在 this.setState 中不起作用。它看起来与控制台中 this 的 ES5 版本相同,所以我得出结论 setState 仍然没有以某种方式绑定

【问题讨论】:

  • 在这里分享你的代码..
  • 当您将组件函数传递给事件处理程序时,例如onClick 等,它不绑定到“this”。所以你要做的就是:onClick={this.yourmethod.bind(this)}。所有其他的东西,比如生命周期方法都会有这个
  • 当您说“不幸的是,当涉及到 this.setState 时这不起作用”这实际上是什么意思?如果您想保留 this 的范围,那么您绝对需要在事件处理程序上使用 .bind(this),这在 ES6 中“工作”。
  • 只需使用name = () => { /* stuff /* } 定义您的方法,这样该方法将自动绑定到组件上下文
  • 我认为从长远来看,学习this 的工作原理会让你的生活更轻松,而不是追逐和检查this 的每次使用。如果你知道this 是如何工作的,那么什么时候不绑定函数就很清楚了。

标签: reactjs ecmascript-6 ecmascript-5


【解决方案1】:

过度简化 this 在 JS 中的工作方式:

  • 如果您将函数作为对象方法调用(例如,instance.foo()),则 this 指的是该对象实例。
  • 如果你自己调用一个函数(例如,foo()),那么this要么是undefined要么是全局对象,这取决于严格模式是否有效。
  • 如果你引用了一个对象方法然后调用它,这意味着你自己调用它,即使它最初是一个对象方法。 (例如,var bar = instance.foo; bar();

再一次,这过于简单化了; MDN有详细信息。

因为这适用于 React,并且如 "Handling Events" 上的 React 文档中所述:

你必须小心 this 在 JSX 回调中的含义。在 JavaScript 中,默认情况下不绑定类方法。如果您忘记绑定this.handleClick 并将其传递给onClick,则实际调用该函数时this 将是undefined

在您的代码中,您将RawInput 呈现为

 <RawInput value={this.state.value} updateValue={this.updateValue}/>

您将引用 updateValue 函数作为一个简单函数传入,因此 this 不会绑定在 updateValue 内。

基本上,任何时候你将一个函数作为 React prop 传递,除非你自己绑定它,否则它很可能是一个错误。症状通常是 this 未定义。在您的代码中,它有点复杂:

this.props.updateValue(modifiedValue);

RawInput 的updateValue 属性是未绑定的函数App.updateValue,但因为您将其调用为this.props.updateValue,所以它被调用就好像它是this.props 的方法 -所以this 指的是RawInput 的props。这就是为什么你的 console.log 显示一个只有两个属性的对象(startupdateValue):不是setState 没有绑定或消失,而是updateValue 没有绑定,所以this 不是你对updateValue 的期望。

如 React 文档所述,要解决此问题:

  • 使用粗箭头函数:updateValue={(value) =&gt; this.updateValue(value)}
  • 使用实验性属性初始化器语法:将 updateValue(modifiedValue) {...} 替换为 updateValue = (modifiedValue) =&gt; {...}
  • React 文档中没有提到,但我经常使用的一种方法:绑定updateValue 自己。例如:
constructor(props) {
    super(props);
    this.updateValue = this.updateValue.bind(this);
}

【讨论】:

  • 乔希,我感激不尽。你甚至追捕我的笔深入。太棒了。我承认我是那些只对文档点头并认为他理解它的密集人之一,直到我真正遇到这个问题并且我通过将头撞到墙上来学习。再次感谢你。使用了胖箭头。我尝试了一种在 SO 上其他地方找到的通用绑定方法(因此使用 BaseComponent 而不是 React.Component),但在这种特殊情况下它不起作用,可能是嵌套的原因。
【解决方案2】:

你可以用这个替换console.log:

console.shallowCloneLog = function(){
    var typeString = Function.prototype.call.bind(Object.prototype.toString)
    console.log.apply(console, Array.prototype.map.call(arguments, function(x){
        switch (typeString(x).slice(8, -1)) {
            case 'Number': case 'String': case 'Undefined': case 'Null': case 'Boolean': return x;
            case 'Array': return x.slice();
            default:
                var out = Object.create(Object.getPrototypeOf(x));
                out.constructor = x.constructor;
                for (var key in x) {
                    out[key] = x[key];
                }
                Object.defineProperty(out, 'constructor', {value: x.constructor});
                return out;
        }
    }));
}

无论如何,关于您的问题,您可以添加这样的方法:

updateValue = () => {...}

in m POV - es6 很酷而且很棒。 es6 类的 React 组件是没用的。坚持使用createClass,你会没事的(如果你愿意,可以使用 mixins!)

【讨论】:

  • 嘿,当 Josh 给出了一个非常全面的答案时,他标记为正确的。这个控制台日志真的很酷,但它可能比我现在需要的要多。你的回答还是对的。我不确定你对最后一部分的意思 - 你认为 es6 很酷,但你不建议将 React 与 es6 一起使用?
  • 我建议使用 es6 来响应除 classes 之外的所有内容。比我更优秀的 JS 开发人员也建议这样做。
  • 知道了。这似乎也是 codepen 最适合的。再次感谢
【解决方案3】:

试试Object.prototype.hasOwnProperty()。例如:

var X = function() {};
X.prototype.setSomething = 'a';
var x = new X();
x.setSomething; // log 'a' here
x.hasOwnPrperty('setSomething') // log false here

就你而言,只需console.log(this.hasOwnProperty('setState'))

【讨论】:

  • 感谢 Timathon,原来我的 this 并不是我想的那样。再次感谢。
【解决方案4】:

您必须将您的 updateValue 函数与组件绑定才能获得正确的上下文 (this)。

在您的情况下,您的父类 BaseComponent 允许您像这样使用继承方法 _bind

class App extends BaseComponent {
  constructor(props){
    super(props);
    this.state={value:'start'};
    this._bind('updateValue');
...

【讨论】:

  • 这个...我在尝试BaseComponent 时错过了这个。谢谢先生。 @Freez
猜你喜欢
  • 1970-01-01
  • 2016-03-29
  • 2013-05-12
  • 2019-04-26
  • 2012-05-19
  • 1970-01-01
  • 2021-07-26
  • 2013-10-31
  • 1970-01-01
相关资源
最近更新 更多