reactjs React MUI:构建包含复杂子菜单控件的菜单

atmip9wb  于 2023-04-11  发布在  React
关注(0)|答案(1)|浏览(130)

我尝试使用MUI Menu构建菜单。当您单击菜单项时,您将根据菜单选择获得弹出控件(如AutocompleteTextFieldSelect或自定义窗体)。我使用Popper显示这些控件。
问题是,当控件显示时,只要我尝试采取任何操作(例如,在TextField中写入内容或在Select中选择值等),它们就会很快失去焦点。
我是新来的MUI,所以我想知道我是否使用了错误的元素或没有处理一些事件。任何帮助将是伟大的!
沙盒链接:
https://codesandbox.io/s/material-ui-autocomplete-forked-exg5ph?file=/src/index.js:0-2765
下面是我的(大大简化的)代码:

import React, { useState } from "react";
import ReactDOM from "react-dom";
import {
  Button,
  Menu,
  MenuItem,
  Fade,
  Box,
  Popper,
  TextField
} from "@material-ui/core";

import "./styles.css";

function App() {
  const [plusAnchorEl, setPlusAnchorEl] = useState(null);
  const [menuItemAnchorEl, setMenuItemAnchorEl] = useState(null);
  const [menuIndex, setMenuIndex] = useState(null);

  const handlePlusClick = (event) => {
    if (event.currentTarget) {
      setPlusAnchorEl(event.currentTarget);
    } else {
      setPlusAnchorEl(null);
    }
  };

  const handleMenuClick = (event, index) => {
    if (event.currentTarget) {
      setMenuItemAnchorEl(event.currentTarget);
      setMenuIndex(index);
    } else {
      setMenuItemAnchorEl(null);
      setMenuIndex(null);
    }
  };

  const handleMenuClose = () => {
    setMenuItemAnchorEl(null);
    setMenuIndex(null);
  };

  return (
    <>
      <Button onClick={handlePlusClick}>+</Button>

      <Menu
        anchorEl={plusAnchorEl}
        open={!!plusAnchorEl}
        onClose={handleMenuClose}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "left"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "left"
        }}
      >
        <MenuItem key="1" onClick={(e) => handleMenuClick(e, "One")}>
          One
          {menuIndex === "One" && (
            <Popper
              open={menuIndex === "One"}
              placement="right-end"
              anchorEl={menuIndex === "One" ? menuItemAnchorEl : null}
              transition
            >
              {({ TransitionProps }) => (
                <Fade {...TransitionProps} timeout={350}>
                  <Box>
                    <TextField />
                  </Box>
                </Fade>
              )}
            </Popper>
          )}
        </MenuItem>
        <MenuItem key="2" onClick={(e) => handleMenuClick(e, "Two")}>
          Two
          {menuIndex === "Two" && (
            <Popper
              open={menuIndex === "Two"}
              placement="right-end"
              anchorEl={menuIndex === "Two" ? menuItemAnchorEl : null}
              transition
            >
              {({ TransitionProps }) => (
                <Fade {...TransitionProps} timeout={350}>
                  <Box>
                    <TextField select>
                      <MenuItem key="2.1">Two.One</MenuItem>
                      <MenuItem key="2.2">Two.Two</MenuItem>
                    </TextField>
                  </Box>
                </Fade>
              )}
            </Popper>
          )}
        </MenuItem>
      </Menu>
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
5t7ly7z5

5t7ly7z51#

这个问题看起来是由于Popper组件在MenuItem组件内部造成的。当你点击Popper内部的TextFieldSelect时,Menu的点击离开监听器会触发,导致菜单关闭,Popper失去焦点。为了解决这个问题,您可以将Popper组件移动到Menu组件之外。

import React, { useState } from "react";
import ReactDOM from "react-dom";
import {
  Button,
  Menu,
  MenuItem,
  Fade,
  Box,
  Popper,
  TextField
} from "@material-ui/core";

import "./styles.css";

function App() {
  const [plusAnchorEl, setPlusAnchorEl] = useState(null);
  const [menuItemAnchorEl, setMenuItemAnchorEl] = useState(null);
  const [menuIndex, setMenuIndex] = useState(null);

  const handlePlusClick = (event) => {
    if (event.currentTarget) {
      setPlusAnchorEl(event.currentTarget);
    } else {
      setPlusAnchorEl(null);
    }
  };

  const handleMenuClick = (event, index) => {
    if (event.currentTarget) {
      setMenuItemAnchorEl(event.currentTarget);
      setMenuIndex(index);
    } else {
      setMenuItemAnchorEl(null);
      setMenuIndex(null);
    }
  };

  const handleMenuClose = () => {
    setMenuItemAnchorEl(null);
    setMenuIndex(null);
  };

  return (
    <>
      <Button onClick={handlePlusClick}>+</Button>

      <Menu
        anchorEl={plusAnchorEl}
        open={!!plusAnchorEl}
        onClose={handleMenuClose}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "left"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "left"
        }}
      >
        <MenuItem key="1" onClick={(e) => handleMenuClick(e, "One")}>
          One
        </MenuItem>
        <MenuItem key="2" onClick={(e) => handleMenuClick(e, "Two")}>
          Two
        </MenuItem>
      </Menu>

      {menuIndex === "One" && (
        <Popper
          open={menuIndex === "One"}
          placement="right-end"
          anchorEl={menuItemAnchorEl}
          transition
        >
          {({ TransitionProps }) => (
            <Fade {...TransitionProps} timeout={350}>
              <Box>
                <TextField />
              </Box>
            </Fade>
          )}
        </Popper>
      )}

      {menuIndex === "Two" && (
        <Popper
          open={menuIndex === "Two"}
          placement="right-end"
          anchorEl={menuItemAnchorEl}
          transition
        >
          {({ TransitionProps }) => (
            <Fade {...TransitionProps} timeout={350}>
              <Box>
                <TextField select>
                  <MenuItem key="2.1">Two.One</MenuItem>
                  <MenuItem key="2.2">Two.Two</MenuItem>
                </TextField>
              </Box>
            </Fade>
          )}
        </Popper>
      )}
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

相关问题