如何解决如何解决此错误,在现有状态转换期间无法更新
我收到此错误:
在现有状态转换期间(例如在
render
)。渲染方法应该是props和 状态。
它发生在这段代码中,callback(newdisplayName)
我知道为什么不应该像我的回调那样触发render
的原因!我试图解决它,但我感到困惑。
我读了这个cannot-update-during-an-existing-state-transition-error-in-react
但是我无法按照建议使用它,就像我应该使用一些lambda一样:
{(newdisplayName) => callback(newdisplayName) }`
但是我有三元运算,所以不一样吗?我也许不必在渲染中进行回调,但是我会更新Redux mapStatetoProps
来触发渲染,所以不知道在其他地方做什么
import React from 'react';
import '../../styles/change-name.css';
import { connect } from 'react-redux';
import Dots from 'react-activity/lib/Dots';
import 'react-activity/lib/Dots/Dots.css';
import { changedisplayName } from '../../redux/userData/user.actions';
class ChangeName extends React.Component {
constructor(props) {
super(props);
const { authUser } = this.props;
this.state = {
displayName: authUser.displayName ?? '',};
}
onSubmit = event => {
event.preventDefault();
this.updateUserName();
};
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
updateUserName() {
const { displayName } = this.state;
const { changeUserdisplayName } = this.props;
changeUserdisplayName(displayName.trim());
}
render() {
const { displayName } = this.state;
const { callback } = this.props;
const { authUser,savingdisplayName,newdisplayName,changedisplayNameErr } = this.props;
const isInvalid = !displayName || !displayName.trim() || displayName.trim().length > 20;
const isAmended = displayName && displayName.trim() !== authUser.displayName;
return (
<div>
<div className="changename">
<form onSubmit={this.onSubmit}>
<input
name="displayName"
value={displayName}
onChange={this.onChange}
type="text"
maxLength="20"
placeholder="display name"
/>
<button className="changenamebutton" disabled={isInvalid || !isAmended} type="submit">
Confirm
</button>
{isInvalid && <p className="error">display name must be between 1 and 20 characters in length</p>}
{changedisplayNameErr && <p className="error">{changedisplayNameErr.message}</p>}
{newdisplayName && <p className="error">New name was saved!</p>}
{newdisplayName ? callback(newdisplayName) : ''}
</form>
</div>
<div>{savingdisplayName ? <Dots /> : null}</div>
</div>
);
}
}
const mapdispatchToProps = dispatch => ({
changeUserdisplayName: displayName => dispatch(changedisplayName(displayName)),});
const mapStatetoProps = state => {
return {
savingdisplayName: state.user.isSavingdisplayName,newdisplayName: state.user.displayName,changedisplayNameErr: state.user.changedisplayNameErrMsg,};
};
export default connect(mapStatetoProps,mapdispatchToProps)(ChangeName);
这是回调的主组件:
import React from 'react';
import '../../styles/profile-page-anonymous.css';
import { compose } from 'recompose';
import { withFirebase } from '../../firebase';
import { AuthUserContext,withAuthorization } from '../../session';
import ChangeName from './ChangeName';
import * as ROLES from '../../constants/roles';
class ProfilePageBase extends React.Component {
constructor(props) {
super(props);
this.state = {
displayName: props.authUser.displayName ?? '',};
this.nameChange = this.nameChange.bind(this);
}
nameChange(displayName) {
this.setState({
displayName,});
}
render() {
let userDetails;
const { authUser } = this.props;
const { displayName } = this.state;
if (authUser) {
userDetails = (
<div>
<div className="profileAnonymous">
<table>
<tbody>
<tr>
<td>display name: </td>
<td>{displayName}</td>
</tr>
<tr>
<td>User ID: </td>
<td>{authUser.uid}</td>
</tr>
<tr>
<td>Anonymous: </td>
<td>{authUser.isAnonymous ? 'True' : 'False'}</td>
</tr>
</tbody>
</table>
</div>
<div>
<h2>Change your display name</h2>
</div>
<div className="profileBoxChangeNameAnonymous">
<ChangeName authUser={authUser} callback={this.nameChange} />
</div>
</div>
);
} else {
userDetails = <p>Unable to get user details. Please try refreshing the page.</p>;
}
return <div>{userDetails}</div>;
}
}
const ProfilePageAnon = props => (
<AuthUserContext.Consumer>
{authUser => (
<div className="profilePageAnonymous">
<ProfilePageBase {...props} authUser={authUser} />
</div>
)}
</AuthUserContext.Consumer>
);
const condition = authUser => authUser && authUser.roles.includes(ROLES.ANON);
const enhance = compose(withAuthorization(condition),withFirebase);
const ProfilePageAnonymous = enhance(ProfilePageAnon);
export default ProfilePageAnonymous;
更新
重构ProfilePageBase
即可解决问题!感谢@DrewReese。我了解了反模式,该模式不以组件状态存储传递的道具。现在,我将ProfilePageBase
重构为无状态组件。
ProfilePageBase
是<AuthUserContext.Consumer>
,监听Firestore会在用户对象上发生变化,因此当ChangName
将新名称保存到Firestore时,ProfilePageBase
会使用AuthUserContext
HOC渲染value
,即具有新名称的用户对象。因此,ChangName
现在不需要思考/了解callback
import React from 'react';
import '../../styles/profile-page-anonymous.css';
import { compose } from 'recompose';
import { withFirebase } from '../../firebase';
import { AuthUserContext,withAuthorization } from '../../session';
import ChangeName from './ChangeName';
import * as ROLES from '../../constants/roles';
function ProfilePageBase({ authUser }) {
return (
<div>
{authUser ? (
<div>
<div className="profileAnonymous">
<table>
<tbody>
<tr>
<td>display name: </td>
<td>{authUser.displayName}</td>
</tr>
<tr>
<td>User ID: </td>
<td>{authUser.uid}</td>
</tr>
<tr>
<td>Anonymous: </td>
<td>{authUser.isAnonymous ? 'True' : 'False'}</td>
</tr>
</tbody>
</table>
</div>
<div>
<h2>Change your display name</h2>
</div>
<div className="profileBoxChangeNameAnonymous">
<ChangeName authUser={authUser} />
</div>
</div>
) : (
<p>Unable to get user details. Please try refreshing the page.</p>
)}
</div>
);
}
const ProfilePageAnon = props => (
<AuthUserContext.Consumer>
{authUser => (
<div className="profilePageAnonymous">
<ProfilePageBase {...props} authUser={authUser} />
</div>
)}
</AuthUserContext.Consumer>
);
const condition = authUser => authUser && authUser.roles.includes(ROLES.ANON);
const enhance = compose(withAuthorization(condition),withFirebase);
const ProfilePageAnonymous = enhance(ProfilePageAnon);
export default ProfilePageAnonymous;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。