How can I tell when this.setState exists in ES6?

白昼怎懂夜的黑 提交于 2019-12-06 17:30:29

To oversimplify how this works in JS:

  • If you call a function as an object method (e.g., instance.foo()) then this refers to that object instance.
  • If you call a function by itself (e.g., foo()), then this is either undefined or the global object, depending on whether strict mode is in effect.
  • If you take a reference to an object method then call it, that means you're calling it by itself, even though it was originally an object method. (E.g., var bar = instance.foo; bar();.

Again, this is an oversimplification; MDN has details.

As this applies to React, and as explained in the React documentation on "Handling Events":

You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.

In your code, you render your RawInput as

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

You're passing a reference updateValue function in as a simple function, so this will not be bound within updateValue.

Basically, any time you pass a function as a React prop, unless you've bound it yourself, it's likely an error. The symptom is typically that this is undefined. In your code, it's a little more complicated:

this.props.updateValue(modifiedValue);

The RawInput's updateValue property is the unbound function App.updateValue, but because you're invoking it as this.props.updateValue, it's being called as if it were a method of this.props - so this refers to the RawInput's props. That's why your console.log is showing an object with only two properties (start and updateValue): it isn't that setState isn't bound or went away, it's that updateValue wasn't bound, so this isn't what you expect within updateValue.

To fix the issue, as the React docs explain:

  • Use a fat arrow function: updateValue={(value) => this.updateValue(value)}
  • Use the experimental property initializer syntax: Replace updateValue(modifiedValue) {...} with updateValue = (modifiedValue) => {...}.
  • Not mentioned in the React docs, but an approach I often use: Bind updateValue yourself. For example:
constructor(props) {
    super(props);
    this.updateValue = this.updateValue.bind(this);
}

you can replace console.log with this:

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

any way, regarding your question, you can add a method like this:

updateValue = () => {...}

in m POV - es6 is cool and great. React components by es6' classes are useless. stick with createClass and you'll be fine (and have mixins if you want!)

Try Object.prototype.hasOwnProperty(). For example:

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

In your case, just console.log(this.hasOwnProperty('setState')).

You have to bind your updateValue function with the component in order to have the correct context (this).

In your case, your parent class BaseComponent allows you to use the herited method _bind like that :

class App extends BaseComponent {
  constructor(props){
    super(props);
    this.state={value:'start'};
    this._bind('updateValue');
...
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!