警告:只能更新一安装或安装组件
这是完全错误:警告:只能更新一安装或安装组件
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
出于某种原因,在页面加载时,它加载的<div id="my-signin2"></div>
的一瞬间重新路由之前。所以用户看到登录页面在屏幕上闪烁,然后路由到正确的页面。
有没有办法在页面加载之前让其重新路由?
理想情况下,我想检查用户是否已登录,如果是,请立即将他路由到特定页面。如果用户不登录,然后向他们展示登录页面(在<div>
)
直到您将gapi.load
方法移动到更高的组件中时,您将始终看到该flash。它所调用的函数是一个承诺,这意味着您的组件将在请求该函数时继续渲染。我会将这一块移动到它自己的组件的高一级,并让您的登录页面成为该组件的子项。
编辑:
下面是一个例子:
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>
)
}
}
所以,现在的<SignIn />
组件将不会被渲染后,才将已授权的请求已经完成,并且用户不会被重定向。
它看起来就像你在componentWillMount
称为this.setState
。顾名思义,组件当时尚未安装 - 因此是您的错误。
如何在页面呈现任何内容之前设置状态? –
如果在渲染页面之前设置了状态,则可能需要的是“props”。将这个组件包装在一个更高阶的组件中,让HOC调用API调用,并将结果'({redirect:true})'作为'props'传递给子组件。 – wrayjs
Np,很高兴你能工作! –
这不与承诺 – shorif2000
@ shorif2000这个例子是使用承诺 –