Reputation: 3538
This is the full error:
index.js:2177 Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.
What does it mean? What am I doing that is generating the error?
This is my login page:
/* global gapi */
class SignIn extends React.Component{
constructor(props){
super(props);
this.state = {
redirect: false
}
this.onSignIn = this.onSignIn.bind(this)
this.updateRedirect = this.updateRedirect.bind(this)
// this.test = this.test.bind(this)
}
componentWillMount() {
console.log('componentWillMount ran')
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: '817677528939-dss5sreclldv1inb26tb3tueac98d24r'
}).then((auth2) => {
console.log( "signed in: " + auth2.isSignedIn.get())
this.setState({
redirect: auth2.isSignedIn.get()
})
})
})
}
updateRedirect() {
this.setState({
redirect: true
})
}
componentDidMount() {
gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 300,
'height': 50,
'longtitle': true,
'theme': 'dark',
'onsuccess': this.onSignIn,
});
}
onSignIn(googleUser) {
console.log('this ran')
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
this.updateRedirect()
}
render() {
return (
this.state.redirect ?
<Redirect to='/options' />
:
<div>
<AppBar title="Pliny" showMenuIconButton={false} zDepth={2} />
<div id="my-signin2"></div>
</div>
)
}
}
export default SignIn
For some reason when the page loads, it is loading the <div id="my-signin2"></div>
for a split second before re-routing. So the user sees the login page flash on the screen and then routed to the correct page.
Is there a way to have it re-route before anything else on the page loads?
Ideally, I'd like to check to see if a user is logged in, and if so, immediately route him to a specific page. If the user isn't logged in, then show them the login page (the <div>
)
Upvotes: 1
Views: 1485
Reputation: 16441
You will always see that flash until you move your gapi.load
method into a higher component. The function it calls is a promise, so that means your component will continue to render while that function is being requested. I would move just that piece into it's own component one level higher, and have your login page be a child of that component.
EDIT:
Here's an example:
class AuthUser extends React.Component {
constructor(props){
super(props);
this.state = {
redirect: false
loaded: false
}
this.onSignIn = this.onSignIn.bind(this)
this.updateRedirect = this.updateRedirect.bind(this)
// this.test = this.test.bind(this)
}
onSignIn(googleUser) {
console.log('this ran')
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
this.updateRedirect()
}
componentWillMount() {
console.log('componentWillMount ran')
gapi.load('auth2', () => {
gapi.auth2.init({
client_id: '817677528939-dss5sreclldv1inb26tb3tueac98d24r'
}).then((auth2) => {
console.log( "signed in: " + auth2.isSignedIn.get())
this.setState({
redirect: auth2.isSignedIn.get(),
loaded: true
})
})
})
}
componentDidMount() {
gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 300,
'height': 50,
'longtitle': true,
'theme': 'dark',
'onsuccess': this.onSignIn,
});
}
updateRedirect() {
this.setState({
redirect: true
});
}
render() {
if(!this.state.loaded) {
return null
}
return this.state.redirect ? <Redirect to='/options' /> : <SignIn />;
}
}
class SignIn extends React.Component{
render() {
return (
<div>
<AppBar title="Pliny" showMenuIconButton={false} zDepth={2} />
<div id="my-signin2"></div>
</div>
)
}
}
So now, the <SignIn />
component won't be rendered until AFTER the auth requests have finished AND the user isn't being redirected.
Upvotes: 1
Reputation: 56
It looks like you've called this.setState
in componentWillMount
. As the name suggests, the component isn't mounted yet at that time -- thus your error.
Upvotes: 0