dropWizard
dropWizard

Reputation: 3538

Warning: Can only update a mounted or mounting component

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

Answers (2)

Chase DeAnda
Chase DeAnda

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

wrayjs
wrayjs

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

Related Questions