将React类组件转换为具有很多回报的功能组件

问题描述 投票:0回答:1

我想使用react钩子将此React类组件更改为react功能组件。我了解如何使用useState设置我的初始状态,但是我需要结构和语法方面的帮助。我想使用无法在类组件中使用的history()。

我不确定如何正确执行此操作,希望能获得一些帮助和指导

我做了这么远的事情:

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

  }

原始组件:

   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))
javascript reactjs syntax react-hooks react-component
1个回答
0
投票

讨论和思考的好话题!

此链接包括此主题的解决方案

LINK : Click Here.

© www.soinside.com 2019 - 2024. All rights reserved.