简体   繁体   中英

SetState from Child Component fails on React Native

I have a Child component which triggers a function in the Parent component. Although the function is triggered, the setState method seems to throw the following error.

Possible Unhandled Promise Rejection (id: 0): undefined is not an object (evaluating '_this12.setState')

Child Component:

return (
    <View style={styles.buttonWrapper}>
        <View style={styles.socialMediaButtonWrapper}>
            <TouchableHighlight style={styles.socialMediaButtonBackFill} onPress={() => {
                this.props.onFacebookAuthenticationPressed()
            }}>
                <View style={[styles.socialMediaButtonFill, {backgroundColor: '#5158bb'}]}>
                    <FontAwesome style={styles.socialMediaButtonTextIconFill} name="facebook" size={20}/>
                </View>
            </TouchableHighlight>
        </View>
    </View>
);

Parent Component (Child Including Code):

<FacebookLoginComponent
    facebookAccessToken={this.state.facebookAccessToken}
    onFacebookAuthenticationPressed = {this.onFacebookAuthenticationPressed}
/>

Function:

onFacebookAuthenticationPressed: function () {
    LoginManager.logInWithReadPermissions(['public_profile', 'email']).then(function (result) {
        if (result.isCancelled) {
            console.log("Login Cancelled");
        } else {
            console.log("Login Successful");
            AccessToken.getCurrentAccessToken().then(
                (data) => {
                    let accessToken = data.accessToken;
                    console.log(accessToken);
                    this.setState({
                        facebookAccessToken: accessToken
                    })
                })
        }
    }, function (error) {
        console.log("some error occurred!!");
    }).done(() => {
        this.markAsComplete();
    })
},

I'm using react-native-fbsdk library for Authentication. The token gets printed from the console.log , but the setState() fails.

Why is this? What's the workaround?

Small fix for the child component (not neccessary, but better):

return (
    <View style={styles.buttonWrapper}>
        <View style={styles.socialMediaButtonWrapper}>
            <TouchableHighlight style={styles.socialMediaButtonBackFill} onPress={this.props.onFacebookAuthenticationPressed}>
                <View style={[styles.socialMediaButtonFill, {backgroundColor: '#5158bb'}]}>
                    <FontAwesome style={styles.socialMediaButtonTextIconFill} name="facebook" size={20}/>
                </View>
            </TouchableHighlight>
        </View>
    </View>
);

constructor of parent component:

this.onFacebookAuthenticationPressed = this.onFacebookAuthenticationPressed.bind(this);

I would not recommend to use bind in the render function. You should really use ES6 though, react native comes with support for that already. Class properties instead of bind:

onFacebookAuthenticationPressed = () => {
    LoginManager.logInWithReadPermissions(['public_profile', 'email']).then((result) => {
        ...
    }, function (error) {
        console.log("some error occurred!!");
    }).done(() => {
        this.markAsComplete();
    })
};

...or with ES5:

onFacebookAuthenticationPressed: function() {
    LoginManager.logInWithReadPermissions(['public_profile', 'email']).then(function (result) {
        ...
    }.bind(this), function (error) {
        console.log("some error occurred!!");
    }).done(function() {
        this.markAsComplete();
    }.bind(this));
};
onFacebookAuthenticationPressed: function () {
    LoginManager.logInWithReadPermissions(['public_profile', 'email']).then((result) => {
        if (result.isCancelled) {
            console.log("Login Cancelled");
        } else {
            console.log("Login Successful");
            AccessToken.getCurrentAccessToken().then(
                (data) => {
                    let accessToken = data.accessToken;
                    console.log(accessToken);
                    this.setState({
                        facebookAccessToken: accessToken
                    })
                })
        }
    }, function (error) {
        console.log("some error occurred!!");
    }).done(() => {
        this.markAsComplete();
    })
},

Notice the result => here, which will pass this to your callback

add bind(this) to the function ....

 <FacebookLoginComponent facebookAccessToken={this.state.facebookAccessToken} onFacebookAuthenticationPressed = {this.onFacebookAuthenticationPressed.bind(this)}// solution /> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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