简体   繁体   English

为什么this.state在native native中是未定义的?

[英]Why this.state is undefined in react native?

I am a complete newbie in react native, react.js, and javascript. 我是反应原生,react.js和javascript的完整新手。 I am Android developer so would like to give RN a try. 我是Android开发人员,所以想试试RN。

Basically, the difference is in onPress ; 基本上,区别在于onPress ;

This code shows 'undefined' when toggle() runs: toggle()运行时,此代码显示'undefined'

class LoaderBtn extends Component {
    constructor(props) {
        super(props);
        this.state = { loading: false };
    }

    toggle() {
        console.log(this.state);
        // let state = this.state.loading;
        console.log("Clicked!")
        // this.setState({ loading: !state })
    }

    render() {
        return (
            <Button style={{ backgroundColor: '#468938' }} onPress={this.toggle}>
                <Text>{this.props.text}</Text>
            </Button>
        );
    }
}

but this code works: 但是这段代码有效:

class LoaderBtn extends Component {
    constructor(props) {
        super(props);
        this.state = { loading: false };
    }

    toggle() {
        console.log(this.state);
        // let state = this.state.loading;
        console.log("Clicked!")
        // this.setState({ loading: !state })
    }

    render() {
        return (
            <Button style={{ backgroundColor: '#468938' }} onPress={() => {this.toggle()}}>
                <Text>{this.props.text}</Text>
            </Button>
        );
    }
}

Can you explain me the difference, please? 你能解释一下这个区别吗?

In Java / Kotlin we have method references, basically it passes the function if signatures are the same, like onPress = () => {} and toggle = () => {} 在Java / Kotlin中,我们有方法引用,基本上如果签名相同则传递函数,如onPress = () => {}toggle = () => {}

But in JS it doesn't work :( 但在JS它不起作用:(

The issue that in the first example toggle() is not bound to the correct this . 在第一个示例中, toggle()没有绑定到正确的this

You can either bind it in the ctor: 你可以在ctor中绑定它:

constructor(props) {
    super(props);
    this.toggle = this.toggle.bind(this);
    ...

Or use an instance function (OK under some circumstances): 或者使用实例函数(在某些情况下可以):

toggle = () => {
    ...
}

This approach requires build changes via stage-2 or transform-class-properties . 此方法需要通过stage-2transform-class-properties构建更改。

The caveat with instance property functions is that there's a function created per-component. 实例属性函数的警告是每个组件创建一个函数。 This is okay if there aren't many of them on the page, but it's something to keep in mind. 如果页面上没有很多,这是可以的,但要记住这一点。 Some mocking libraries also don't deal with arrow functions particularly well (ie, arrow functions aren't on the prototype, but on the instance). 一些模拟库也没有特别好地处理箭头函数(即箭头函数不在原型上,而是在实例上)。

This is basic JS; 这是基本的JS; this article regarding React Binding Patterns may help. 这篇关于React Binding Patterns的文章可能有所帮助。

I think what is happening is a matter of scope. 我认为正在发生的事情是范围问题。 When you use onPress={this.toggle} this is not what you are expecting in your toggle function. 当您使用onPress={this.toggle}这不是您在切换功能中所期望的。 However, arrow functions exhibit different behavior and automatically bind to this . 但是,箭头函数表现出不同的行为并自动绑定this You can also use onPress={this.toggle.bind(this)} . 你也可以使用onPress={this.toggle.bind(this)}

Further reading - 进一步阅读 -

ES6 Arrow Functions ES6箭头功能

.bind() .bind()

What is happening in this first example is that you have lost scope of "this". 第一个例子中发生的事情是你已经失去了“这个”的范围。 Generally what I do is to define all my functions in the constructor like so: 通常我所做的是在构造函数中定义我的所有函数,如下所示:

constructor(props) {
    super(props);
    this.state = { loading: false };
    this.toggle = this.toggle.bind(this);
}

In the second example, you are using ES6 syntax which will automatically bind this (which is why this works). 在第二个示例中,您使用的是ES6语法,它将自动绑定它(这就是为什么这样做)。

Then inside of you onPress function, you need to call the function that you built. 然后在你的onPress函数里面,你需要调用你构建的函数。 So it would look something like this, 所以它看起来像这样,

onPress={this.toggle}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM