2017-08-06 50 views
1

我想使用Facebook API在我的页面上添加Facebook登录。当用户点击使用Facebook登录按钮我希望页面重定向到另一个。为此,我做了以下操作:获取“警告:setState(...):只能更新已安装或正在安装的组件。”设置“FB.Event.subscribe()”函数内部状态时发生错误

componentDidMount() { 
    window.fbAsyncInit = function() { 
    FB.init({ 
     appId   : '1947842912095857', 
     autoLogAppEvents : true, 
     xfbml   : true, 
     version   : 'v2.10' 
    }); 
    FB.AppEvents.logPageView(); 
    FB.getLoginStatus((response) => { 
     if (response.status === 'connected') { 
     console.log('Logged in.'); 
     this.setState({ loggedIn: true }); 
     } 
     else { 
     } 
    }); 

    // login callback implementation goes inside the function() { ... } block 
    FB.Event.subscribe('auth.statusChange', (response) => { 
    if (response.authResponse) { 
     console.log('Welcome! Fetching your information.... '); 
     FB.api('/me', (response) => { 
     console.log('Good to see you, ' + response.name + '.'); 
     this.setState({ loggedIn: true }); 
     // if(!this.state.loggedIn){ 
     // } 
     }); 
    } else { 
     console.log('User cancelled login or did not fully authorize.'); 
    } 
    }); 
}.bind(this); 
    (function(d, s, id){ 
    var js, fjs = d.getElementsByTagName(s)[0]; 
    if (d.getElementById(id)) {return;} 
    js = d.createElement(s); js.id = id; 
    js.src = "//connect.facebook.net/en_US/sdk.js"; 
    fjs.parentNode.insertBefore(js, fjs); 
    }(document, 'script', 'facebook-jssdk')); 

    var s = '<div class="fb-login-button" ' + 
     'data-scope="public_profile,email" data-size="large" ' + 
     'data-show-faces="false" data-auto-logout-link="true" ' + 
     'href="javascript:void(0)""></div>'; 

    var div = document.getElementById('social-login-button-facebook') 
    div.innerHTML = s; 
} 

首先我初始化Facebook API。然后我打电话FB.getLoginStatus()看看用户是否已经登录。在回调中,我将this.state.loggedIn设置为true,它工作正常。然而,在FB.Event.subscribe()功能时,我称之为this.setState功能我得到以下错误:

Warning: setState(...): Can only update a mounted or mounting component. 

我试图解决这个问题,我试图解决办法是检查用户是否是已经登录,然后设置状态。

if(!this.state.loggedIn){ 
    this.setState({ loggedIn: true }); 
} 

然后我摆脱了错误。但我不知道这是为什么。 有没有人知道它为什么可以在FB.getLoginStatus()中调用this.setState(),但不在FB.Event.subscribe()中,以及为什么它只能在用户尚未登录时设置状态?

感谢您花时间阅读本文。

回答

1

这与请求的异步性质有关。虽然组件可能在某个时间点安装,但如果有未完成的请求直到卸载该组件后才能完成,那么您将尝试在未安装的组件上使用setState

例如:

class LoginComponent extends Component { 

    componentWillMount() { 
     // This request will happen whenever the component mounts 
     Request.get('/login-token').then(() => { 
      dispatch({type: SET_TOKEN, token: 'blah blah'}); 

      // Whoops, what if there was already a login token 
      // and the user was redirected? This will attempt to set 
      // state on a component that has been unmounted due to redirect 
      this.setState({loggedIn: true}); 
     }); 
    } 

    componentWillReceiveProps(props) { 
     // This will only redirect if there is already a token 
     if (props.token) { 
      browserHistory.push('/some-logged-in-page'); 
     } 
    } 

    render() { 
     return (
      // ... 
     ); 
    } 
} 

在这个例子中,请求将尽一切时间来获得令牌的组件坐骑。但是我们正在检查是否通过道具传入了令牌,并且可能会重定向。由于请求的异步性质,如果存在传入的令牌,并且用户被重定向,则请求仍然会完成并尝试setState,但该组件在此之前已被卸载。

看看这个react blog post它讨论处理异步请求的问题,并提出了安全取消componentWillUnmount中的请求的方法。

+0

谢谢,这是有道理的。现在我明白了为什么在设置它之前检查状态。 – martin36

相关问题