简体   繁体   中英

I am trying to implement menuitem in react but getting error

  • I am using MenuItem to implement dropdown menu in react.
  • I have imported the package also then too I am facing the error when running the server.
  • I tried looking for solution but not getting any exact method to solve the problem.
  • Or is there any other way to implement the same?
  • I want to have 2 options under drop down menu "User" and "Admin", so while registration the user will select his role.
import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { registerUser } from "../../actions/authActions";
import classnames from "classnames";
import MenuItem from '@material-ui/core/MenuItem';


class Register extends Component {
  constructor() {
    super();
    this.state = {
      name: "",
      email: "",
      password: "",
      password2: "",
      mobile: "",
      errors: {}
    };
  }

  componentDidMount() {
    // If logged in and user navigates to Register page, should redirect them to dashboard
    if (this.props.auth.isAuthenticated) {
      this.props.history.push("/dashboard");
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.errors) {
      this.setState({
        errors: nextProps.errors
      });
    }
  }

  onChange = e => {
    this.setState({ [e.target.id]: e.target.value });
  };

  onSubmit = e => {
    e.preventDefault();

    const newUser = {
      name: this.state.name,
      email: this.state.email,
      password: this.state.password,
      password2: this.state.password2,
      mobile: this.state.mobile
    };

    this.props.registerUser(newUser, this.props.history);
  };

  render() {
    const { errors } = this.state;

    return (
      <div className="container">
        <div className="row">
          <div className="col s8 offset-s2">
            <div className="col s12" style={{ paddingLeft: "11.250px" }}>
              <h4>
                <b>Register</b>
              </h4>
              <p className="grey-text text-darken-1">
                Already have an account? <Link to="/">Log in</Link>
              </p>
            </div>
            <form noValidate onSubmit={this.onSubmit}>

              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.name}
                  error={errors.name}
                  id="name"
                  type="text"
                  className={classnames("", {
                    invalid: errors.name
                  })}
                />
                <label htmlFor="name">Name</label>
                <span className="red-text">{errors.name}</span>
              </div>

              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.email}
                  error={errors.email}
                  id="email"
                  type="email"
                  className={classnames("", {
                    invalid: errors.email
                  })}
                />
                <label htmlFor="email">Email</label>
                <span className="red-text">{errors.email}</span>
              </div>

              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.password}
                  error={errors.password}
                  id="password"
                  type="password"
                  className={classnames("", {
                    invalid: errors.password
                  })}
                />
                <label htmlFor="password">Password</label>
                <span className="red-text">{errors.password}</span>
              </div>

              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.password2}
                  error={errors.password2}
                  id="password2"
                  type="password"
                  className={classnames("", {
                    invalid: errors.password2
                  })}
                />
                <label htmlFor="password2">Confirm Password</label>
                <span className="red-text">{errors.password2}</span>
              </div>

              <div className="input-field col s12">
                <input
                  onChange={this.onChange}
                  value={this.state.mobile}
                  error={errors.mobile}
                  id="mobile"
                  type="text"
                  className={classnames("", {
                    invalid: errors.mobile
                  })}
                />
                <label htmlFor="mobile">Mobile No.</label>
                <span className="red-text">{errors.mobile}</span>
              </div>

              <Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
                Open Menu
              </Button>

              <Menu
              id="simple-menu"
              anchorEl={anchorEl}
              keepMounted
              open={Boolean(anchorEl)}
              onClose={handleClose}
              >
                <MenuItem onClick={handleClose}>Profile</MenuItem>
                <MenuItem onClick={handleClose}>My account</MenuItem>
                <MenuItem onClick={handleClose}>Logout</MenuItem>
              </Menu>


              <div className="col s12" style={{ paddingLeft: "11.250px" }}>
                <button
                  style={{
                    width: "150px",
                    borderRadius: "3px",
                    letterSpacing: "1.5px",
                    marginTop: "1rem"
                  }}
                  type="submit"
                  className="btn btn-large waves-effect waves-light hoverable blue accent-3"
                >
                  Create
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

Register.propTypes = {
  registerUser: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  errors: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth,
  errors: state.errors
});

export default connect(
  mapStateToProps,
  { registerUser }
)(withRouter(Register));

The problem with below is handleClose and anchorEl property. I think you probably have copied it from material site. And the example from where you copied is of f unctional component in react and you are using a class component.

Material site has demo with functional component. you can check source of code you copied https://material-ui.com/components/menus/

<Menu
          id="simple-menu"
          anchorEl={anchorEl}
          keepMounted
          open={Boolean(anchorEl)}
          onClose={handleClose}
          >
            <MenuItem onClick={handleClose}>Profile</MenuItem>
            <MenuItem onClick={handleClose}>My account</MenuItem>
            <MenuItem onClick={handleClose}>Logout</MenuItem>
          </Menu>

update it to class level anchorEl and handleClose it will work.

demo link of functional menu of material site. check demo.js see anchorEL and handleclose and implement it in your logic https://codesandbox.io/s/sm1zv?file=/demo.js

First, Button and Menu are not defined so import them:

import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';

Next, anchorEl , handleClick , handleClose are not defined

  1. You can use a ref for anchorEl :
class Register extends Component {
  constructor() {
    super();
    this.state = {
      name: "",
      email: "",
      password: "",
      password2: "",
      mobile: "",
      errors: {},
      open: false
    };
    this.menuRef = React.createRef();
  }

  ...
  1. Next, add handleClick and handleClose methods:
handleClose = () => {
  this.setState({
    open: false
  });
};

handleClick = () => {
  this.setState({
    open: true
  });
};

Also make sure to add state.open: false to the constructor.

  1. Finally, change the Button and Menu markup to use the newly defined properties:
<Button
  aria-controls="simple-menu"
  aria-haspopup="true"
  onClick={this.handleClick}
>
  Open Menu
</Button>

<Menu
  id="simple-menu"
  ref={this.menuRef}
  anchorEl={this.menuRef}
  keepMounted
  open={this.state.open}
  onClose={this.handleClose}
>
  <MenuItem onClick={this.handleClose}>Profile</MenuItem>
  <MenuItem onClick={this.handleClose}>My account</MenuItem>
  <MenuItem onClick={this.handleClose}>Logout</MenuItem>
</Menu>

Here's a demo of the Menu opening and closing, with the react-router functionality taken out

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM