【问题标题】:Warning: Can only update a mounted or mounting component警告:只能更新已安装或正在安装的组件
【发布时间】:2017-11-17 21:22:23
【问题描述】:

这是完整的错误:

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.

这是什么意思?我在做什么会产生错误?

这是我的登录页面:

/* 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

由于某种原因,当页面加载时,它会在重新路由之前加载&lt;div id="my-signin2"&gt;&lt;/div&gt; 片刻。所以用户看到登录页面在屏幕上闪烁,然后路由到正确的页面。

有没有办法让它在页面上的其他内容加载之前重新路由?

理想情况下,我想检查用户是否已登录,如果已登录,则立即将他引导至特定页面。如果用户没有登录,则向他们显示登录页面(&lt;div&gt;

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    在您将 gapi.load 方法移动到更高的组件之前,您将始终看到该闪烁。它调用的函数是一个承诺,这意味着您的组件将在请求该函数时继续呈现。我会将该部分移到它自己的组件更高一级,并让您的登录页面成为该组件的子级。

    编辑:

    这是一个例子:

    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>
            )
        }
    }
    

    所以现在,&lt;SignIn /&gt; 组件将在身份验证请求完成并且用户没有被重定向之后才会呈现。

    【讨论】:

    【解决方案2】:

    您似乎在componentWillMount 中调用了this.setState。顾名思义,该组件当时尚未安装 - 因此您的错误。

    【讨论】:

    • 如何在页面呈现任何内容之前设置状态?
    • 如果在渲染页面之前设置了状态,那么您可能想要的是props。将此组件包装在更高阶的组件中,让 HOC 进行 API 调用,并将结果 ({ redirect: true }) 作为 props 传递给子组件。
    猜你喜欢
    • 2017-04-26
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-22
    • 2017-03-02
    • 2019-08-15
    相关资源
    最近更新 更多