简体   繁体   中英

React JS / Material UI - Call method from imported Component

I'm trying to call the handleLoginOpen method from LoginModal.js, which I imported in File1.js. File1 is actually a component nested in an AppBar, where i have an account IconButton that shows two MenuItem: Login or Register. If I press login I would like to show a Modal with the login form.

Here the two files:

File1.js:

import React from "react";
import { IconButton, Menu, MenuItem } from "@material-ui/core";
import AccountCircleIcon from "@material-ui/icons/AccountCircle";
import LoginModal from "../components/LoginModal";

export default function AccountNotRegistered() {
  const [anchorEl, setAnchorEl] = React.useState(null);

  const isMenuOpen = Boolean(anchorEl);

  const handleProfileMenuOpen = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleProfileMenuClose = () => {
    setAnchorEl(null);
  };

  const menuId = "account-menu";
  const renderMenu = (
    <Menu
      anchorEl={anchorEl}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      id={menuId}
      keepMounted
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      open={isMenuOpen}
      onClose={handleProfileMenuClose}
    >
      <MenuItem onClick={handleLoginOpen}>Login</MenuItem> <------------------- HERE I CALL THE METHOD
      <MenuItem onClick={handleProfileMenuClose}>Register</MenuItem>
    </Menu>
  );

  return (
    <div>
      <IconButton color="inherit" onClick={handleProfileMenuOpen}>
        <AccountCircleIcon />
      </IconButton>
      <LoginModal />
      {renderMenu}
    </div>
  );
}

LoginModal.js:


import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Modal from "@material-ui/core/Modal";
import { Backdrop } from "@material-ui/core";
import Fade from "@material-ui/core/Fade";

const useStyles = makeStyles((theme) => ({
  modal: {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  },
  paper: {
    backgroundColor: theme.palette.background.paper,
    border: "2px solid #000",
    boxShadow: theme.shadows[5],
    padding: theme.spacing(2, 4, 3),
  },
}));

export default function LoginModal() {
  const classes = useStyles();
  const [open, setOpen] = React.useState(false);

  const handleLoginOpen = () => { <----------------------------------HERE IS THE METHOD
    setOpen(true);
  };

  const handleLoginClose = () => {
    setOpen(false);
  };

  return (
    <Modal
      aria-labelledby="transition-modal-title"
      aria-describedby="transition-modal-description"
      className={classes.modal}
      open={open}
      onClose={handleLoginClose}
      closeAfterTransition
      BackdropComponent={Backdrop}
      BackdropProps={{
        timeout: 500,
      }}
    >
      <Fade in={open}>
        <div className={classes.paper}>
          <h2 id="transition-modal-title">Transition modal</h2>
          <p id="transition-modal-description">
            react-transition-group animates me.
          </p>
        </div>
      </Fade>
    </Modal>
  );
}

Thank you for your help!

If you want to use a method of another component you need to create parent-child relation of components and then pass those methods as a prop to child component.

You should use/call <LoginModal /> inside File1.js where this LoginModel would take a prop value for visibility of modal such as isModalShown and then a function to close the modal such as closeModal

so when you call the component it would look like:

<LoginModal isModalShown={isModalShown} closeModal={closeModal} />

You need to maintain the state variable in File1.js since showing/hiding modal is done in the same file.

import React from "react";
import { IconButton, Menu, MenuItem } from "@material-ui/core";
import AccountCircleIcon from "@material-ui/icons/AccountCircle";
import LoginModal from "../components/LoginModal";

export default function AccountNotRegistered() {
    const [anchorEl, setAnchorEl] = React.useState(null);
    const [isModalShown, toggleModal] = React.useState(false);

    const closeModal = () => toggleModal(false)

    const openModal = () => toggleModal(false)

    const isMenuOpen = Boolean(anchorEl);

    const handleProfileMenuOpen = (event) => {
        setAnchorEl(event.currentTarget);
    };

    const handleProfileMenuClose = () => {
        setAnchorEl(null);
    };

    const menuId = "account-menu";
    const renderMenu = (
        <React.Fragment>
            <Menu
                anchorEl={anchorEl}
                anchorOrigin={{ vertical: "top", horizontal: "right" }}
                id={menuId}
                keepMounted
                transformOrigin={{ vertical: "top", horizontal: "right" }}
                open={isMenuOpen}
                onClose={handleProfileMenuClose}>
                    <MenuItem onClick={openModal}>Login</MenuItem>
                    <MenuItem onClick={handleProfileMenuClose}>Register</MenuItem>
            </Menu>
        </React.Fragment>
    );

    return (
        <div>
        <IconButton color="inherit" onClick={handleProfileMenuOpen}>
            <AccountCircleIcon />
        </IconButton>
        <LoginModal isModalShown={isModalShown} closeModal={closeModal} />
        {renderMenu}
        </div>
    );
}

and then in the LoginModal.js

export default function LoginModal(props) {
  const classes = useStyles();

  return (
    <Modal
      aria-labelledby="transition-modal-title"
      aria-describedby="transition-modal-description"
      className={classes.modal}
      open={props.isModalShown}
      onClose={props.closeModal}
      closeAfterTransition
      BackdropComponent={Backdrop}
      BackdropProps={{
        timeout: 500,
      }}
    >
      <Fade in={open}>
        <div className={classes.paper}>
          <h2 id="transition-modal-title">Transition modal</h2>
          <p id="transition-modal-description">
            react-transition-group animates me.
          </p>
        </div>
      </Fade>
    </Modal>
  );
}

I believe you want to show the modal on click of Register as well, you can create a wrapper for this Modal component and then pass custom props to it, which would then takes care of rendering <LoginModal /> or <RegisterModal />

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