Reactjs 如何修复此错误在现有状态转换期间无法更新
我得到这个错误: 无法在现有状态转换期间更新(例如在Reactjs 如何修复此错误在现有状态转换期间无法更新,reactjs,callback,render,ternary,Reactjs,Callback,Render,Ternary,我得到这个错误: 无法在现有状态转换期间更新(例如在 渲染)。渲染方法应该是道具和工具的纯功能 国家 它发生在这段代码的回调(newDisplayName) 我知道为什么渲染不应该像我的回调那样触发!我试图解决它,但我很困惑。 我读了这个 但我不能让它像建议的那样工作,比如我应该使用一些lambda,比如: {(newDisplayName) => callback(newDisplayName) }` 但是我有一个三元运算,所以它是不一样的,对吗?我可能不需要在渲染中进行回调,但我得
渲染
)。渲染方法应该是道具和工具的纯功能
国家
它发生在这段代码的回调(newDisplayName)
我知道为什么渲染不应该像我的回调那样触发!我试图解决它,但我很困惑。
我读了这个
但我不能让它像建议的那样工作,比如我应该使用一些lambda,比如:
{(newDisplayName) => callback(newDisplayName) }`
但是我有一个三元运算,所以它是不一样的,对吗?我可能不需要在渲染中进行回调,但我得到了触发渲染的Reduxmapstatetops
更新,因此不知道还有什么地方可以这样做
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);
什么是props.callback
?它有什么作用?渲染方法应该是纯函数,这意味着它们不应该调用任何产生副作用的函数。props.callback
是对母组件的回调。是的,我知道渲染应该是纯的,这就是为什么我问这个问题如何解决这个问题。在渲染过程中,为了不更新某个状态值,您做了什么?看起来,callback
可能正在对从redux传入的newDisplayName
prop执行某些操作。callback(newDisplayName)
做什么?我看到ChangeName
被传递callback={this.nameChange}
,它正在更新父级中的状态。无法从子对象的渲染中执行此操作newDisplayName
似乎是从redux传递的,因此任何本地组件状态更新都应该在生命周期方法中发生。是否有原因ProfilePageBase
不订阅newDisplayName
存储?或者您是否需要ChangeName
调用回调来更新父级中的状态?巧合的是,在组件状态下存储传递的道具也是一种react反模式。我所做的只是问了一堆问题,让您知道react反模式,其余的都是您自己做的:p顺便说一句,你可以回答/解决你自己的问题。
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;
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;