1
votes

Impossible d'appeler setState dans un composant non monté tout en travaillant sur la partie de connexion

Je travaille sur une fonctionnalité de connexion avec Facebook et je vois ce problème dans ma console. Il dit:

class SocialLogin extends Component{
  constructor(props){
    super(props);
    this.state={
        userData:""
    };
  }

componentDidMount() {
    (function (d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        console.log("d",d);
        console.log("s",s);
        console.log("id",id);
        debugger
        if (d.getElementById(id)) {
            return;
        }
        js = d.createElement(s);
        console.log("js",js);
        js.id = id;
        js.src = "https://connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));


    window.fbAsyncInit = ()=> {
        window.FB.init({
            appId: FACEBOOK_APP_ID,//Change with your Facebook app id
            autoLogAppEvents: true,
            xfbml: true,
            version: 'v3.0'
        });

        window.FB.Event.subscribe('auth.statusChange', response => {
             console.log("event",response);
             debugger
            if (response.authResponse) {
                this.checkLoginState();
            } else {
                console.log('[FacebookLoginButton] User cancelled login or did not fully authorize.');
            }
        });
    };
}
// componentDidUpdate(){
//     console.log("updateduserprofile",userProfile);
//     this.props.loginUser(userProfile);
//     debugger
//    //window.location.href="https://rooter-web-app-dev.firebaseapp.com/home/cricket"
// }

checkLoginState(){
    debugger
    window.FB.getLoginStatus(function(response) {
        console.log("response inside checklogin",response);
        this.statusChangeCallback(response);
    }.bind(this));
}

login(){
    window.FB.login(this.checkLoginState(), {scope: 'email'});
}

statusChangeCallback(response) {
    console.log("response",response);
    accessToken =response && response.authResponse && response.authResponse.accessToken;

    if (response.status === 'connected') {
        this.testAPI();

    } else if (response.status === 'not_authorized') {
        console.log("[FacebookLoginButton] Person is logged into Facebook but not your app");
    } else {
        console.log("[FacebookLoginButton] Person is not logged into Facebook");
    }
}

testAPI() {

    window.FB.api('/me' ,(response)=> {
        console.log("testAPI",response);

       if(response){
           userProfile = {
                  auth:accessToken,
                  id:response.id,
                  name:response.name,
                  provider: "Facebook",

                };
                console.log("userProfile",userProfile);
                this.setData(userProfile);
       }

        console.log('[FacebookLoginButton] Successful login for: ', response);
    });

}
setData=(userProfile)=>{
    this.setState({
        userData:userProfile
    },()=>{
        console.log('inside setData');
        if(userProfile!==undefined){
            console.log("inside callback",userProfile);
            this.props.loginUser(this.state.userData);
        }

    });
}

render(){
    return (
        <div style={loginstyle}>
        <button onClick={()=>this.login() }  className="loginBtn loginBtn--facebook">
          Login with Facebook
         </button>

       </div>
    )
}                                                                                                                                                                                                                                     z

Je reçois le journal de la console de userProfile où nous voyons la réponse de Facebook et après cela, l'exécution du code s'arrête. Je ne vois pas ma connexion être distribuée à cause de cela, le setState devrait se produire.

Voici le code de connexion et nous ne faisons que setState d'une part.

Can't call setState (or forceUpdate) on an unmounted component. 
This is a no-op, but it indicates a memory leak in your application.     
To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.


0 commentaires

3 Réponses :


0
votes

Le problème est que vous essayez de définir votre état une fois que votre composant a été démonté (ex: navigation vers une autre page). Donc, pour éviter que cela ne se produise, essayez celui-ci:

if(this._isMounted)
{
    this.setData(userProfile);
}

Et dans ce testAPI ajoutez ceci:

    _isMounted = false;

    componentDidMount(){
        this._isMounted = true;
    }

    componentWillUnmount(){
        this._isMounted = false;
    }

Et il ne mettra à jour l'état que si le composant est monté


0 commentaires

1
votes

avant de mettre à jour l'état du composant, vous devez vérifier s'il est monté ?? s'il n'est pas monté, ne mettez pas à jour l'état de celui-ci, pour ce faire, vous devrez maintenir l'indicateur indiquant l'état de montage du composant consiger le code suivant

constructor(props){
   super(props);
   this.state={
      userData:""
   };
  //initially its false
   this.mount=false
 }
componentWillUnMount(){
    //make it false here
    this.mount=false;
}
componentDidMount() {
//make it true when mounted
    this.mount=true;
}

maintenant avant d'utiliser setState, assurez-vous que this.mount est vrai, j'espère que cela vous aidera!


0 commentaires

1
votes

vous devez vous désabonner lorsque le composant sera démonté.

componentWillUnmmount() {
  window.FB.Event.unsubscribe('auth.statusChange', this.onAuthStatusChange)
}

...

window.FB.Event.subscribe('auth.statusChange', this.onAuthStatusChange)

et lorsque le composant seraUnmmount

onAuthStatusChange = response => {
  console.log("event",response);
  if (response.authResponse) {
    this.checkLoginState();
  } else {
    console.log('[FacebookLoginButton] User cancelled login or did not fully authorize.');
  }
}


0 commentaires