2017-08-06 61 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

相關問題