[英]Convert React Class Component to Functional Component with many returns
I want to change this react class component to a react functional component using react hooks.我想使用 react hooks 将此 react 类组件更改为 react 功能组件。 I understand how to use the useState to set my initial states but I need help with the structuring and syntax.
我了解如何使用 useState 来设置我的初始状态,但我需要结构和语法方面的帮助。 I want to use history() which cannot be used in class components.
我想使用不能在类组件中使用的 history()。
I am not sure how to do this properly and would appreciate some help and guidance我不知道如何正确地做到这一点,希望得到一些帮助和指导
WHAT I HAVE DONE SO FAR:到目前为止我做了什么:
export function ProfileMenu(){
const history = useHistory()
const ref = useRef()
const [showUserMenu, setShowUserMenu] = useState(false)
const [showProfile, setShowProfile] = useState(false)
const [showPasswordPopup, setShowPasswordPopup] = useState(false)
const [oldPasswordError, setOldPasswordError] = useState(null)
const [newPasswordConfirmed, setNewPassswordConfirmed] = useState(null)
const [newPasswordMatchError, setNewPasswordMatchError] = useState(null)
userMenuRef = React.createRef(),
renderUserIcon = () => {
return (
<div
className="ml-1"
ref={this.userMenuRef}
aria-controls="menu-list-grow"
aria-haspopup="true"
onClick={() => this.setState({ showUserMenu: !this.state.showUserMenu })}
>
<Avatar firstName={this.props.firstName} lastName={this.props.lastName} suspended={false} />
<Popper
open={this.state.showUserMenu}
anchorEl={this.userMenuRef.current}
transition
disablePortal
placement="bottom-end"
className={styles.logout}
>
{({ TransitionProps, placement }) => (
<Grow {...TransitionProps} style={{ transformOrigin: 'right bottom' }}>
<Paper id="menu-list-grow">
<ClickAwayListener onClickAway={() => this.setState({ showUserMenu: false })}>
<UserMenu>
<UserMenuItem
onClick={() => this.setState({ showProfile: !this.state.showProfile })}
>
Edit Profile
</UserMenuItem>
<UserMenuItem
onClick={() => history.push('/editprofile')}
>
Change Password
</UserMenuItem>
<UserMenuItem onClick={() => this.props.logout()}>Log out</UserMenuItem>
</UserMenu>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</div>
)
}
}
ORIGINAL COMPONENT:原始组件:
export class Header extends Component {
state = {
showUserMenu: false,
showProfile: false,
showPasswordPopup: false,
oldPasswordError: null,
newPasswordConfirmed: null,
newPasswordMatchError: null,
}
userMenuRef = React.createRef()
renderUserIcon() {
return (
<div
className="ml-1"
ref={this.userMenuRef}
aria-controls="menu-list-grow"
aria-haspopup="true"
onClick={() => this.setState({ showUserMenu: !this.state.showUserMenu })}
>
<Avatar firstName={this.props.firstName} lastName={this.props.lastName} suspended={false} />
<Popper
open={this.state.showUserMenu}
anchorEl={this.userMenuRef.current}
transition
disablePortal
placement="bottom-end"
className={styles.logout}
>
{({ TransitionProps, placement }) => (
<Grow {...TransitionProps} style={{ transformOrigin: 'right bottom' }}>
<Paper id="menu-list-grow">
<ClickAwayListener onClickAway={() => this.setState({ showUserMenu: false })}>
<UserMenu>
<UserMenuItem
onClick={() => this.setState({ showProfile: !this.state.showProfile })}
>
Edit Profile
</UserMenuItem>
<UserMenuItem
onClick={() => history.push('/editprofile')}
>
Change Password
</UserMenuItem>
<UserMenuItem onClick={() => this.props.logout()}>Log out</UserMenuItem>
</UserMenu>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</div>
)
}
renderNavContent() {
return (
<div className={styles.border}>
{this.props.tabs.map(({ text, url, exact = true }, i) => (
<NavLink
key={i}
to={url}
className={styles.tab}
activeClassName={
matchPath(window.location.pathname, { path: url, exact }) ? styles.active : styles.tab
}
>
{text}
</NavLink>
))}
</div>
)
}
renderProfilePopup() {
const onClose = () =>
this.setState({
showProfile: false,
})
return (
<Mutation
mutation={UPDATE_USER}
key={'UPDATE_USER'}
update={(cache, { data: { updateUser } }) => {
this.props.extendUser(updateUser)
}}
>
{(mutation, { error }) => (
<EditContact
open={this.state.showProfile}
user={this.props.user}
error={error}
onClose={onClose}
_onSubmit={async (form) => {
await mutation({ variables: { user: form } })
this.setState({ showProfile: false })
this.props.enqueueSnackbar('User was updated successfully', { variant: 'success' })
}}
/>
)}
</Mutation>
)
}
renderPasswordPopup() {
const onClose = () => {
this.setState({
showPasswordPopup: false,
})
}
return (
<ChangePasswordModal
open={this.state.showPasswordPopup}
onClose={onClose}
user={this.props.user}
_onSubmit={async (form) => {
await this.props.changePassword(
form.oldPassword,
form.newPassword,
form.newPasswordConfirmed
)
this.props.enqueueSnackbar('Password was updated successfully', { variant: 'success' })
}}
/>
)
}
render() {
return (
<div className={styles.header}>
<Grid container justify="space-between" alignItems="center">
<Grid>
<Grid container alignItems="center">
<Hidden mdUp>
<IconButton
color="inherit"
onClick={() => this.props.setMenuState(true)}
edge="start"
>
<MenuIcon />
</IconButton>
</Hidden>
<div className={styles.organization}>{this.props.organization}</div>
</Grid>
</Grid>
<Grid>
<Grid container justify="flex-end" alignItems="center">
<Tooltip className="mx-2" title="Support">
<SupportIcon />
</Tooltip>
<Tooltip className="mx-2" title="Notifications">
<div className="ak-trigger">
<NotificationsIcon />
<AnnounceKit
catchClick=".ak-trigger"
widget={process.env.REACT_APP_ANNOUNCE_KIT_WIDGET_URL}
/>
</div>
</Tooltip>
<div className={classnames('mx-2', styles.user)}>
<Hidden xsDown>
<div onClick={() => this.setState({ showUserMenu: !this.state.showUserMenu })}>
<div>
{this.props.firstName} {this.props.lastName}
</div>
<div>{this.props.email}</div>
</div>
</Hidden>
{this.renderUserIcon()}
</div>
</Grid>
</Grid>
</Grid>
{this.renderProfilePopup()}
{this.renderPasswordPopup()}
<h1 className={styles.title}>{this.props.title}</h1>
{this.renderNavContent()}
</div>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(withSnackbar(Header))
Good topic for discussion and thinking a bit !!讨论和思考的好话题!!
This link includes the solution to this topic此链接包含此主题的解决方案
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.