我想在 React-MUI 中有一个对话框作为一个单独的组件

I want to have a dialog as a separate component in React-MUI

我正在使用 React 和 MUI (v5)

我想在我的组件中显示一个对话框,但我希望这个对话框作为一个单独的组件,例如:

function MyComponent() {

    const [ openDialog, setOpenDialog ] = useState(false);

    const handleOpenDialog = () => {
        setOpenDialog(true);
    };

    return (
        <React.Fragment>
            <Button variant="contained" size="medium" onClick={handleOpenDialog}>
                Open Dialog
            </Button>

            <CreateCategory openDialog={openDialog} />

            <Box>
              ...
            </Box>
        </React.Fragment>
    );
}

对话框如下:


export default function CreateCategory(props) {
  const [openDialog, setOpenDialog] = useState(props.openDialog);
  const [newCategoryName, setNewCategoryName] = useState("");

  const handleDialogClose = () => {
    setOpenDialog(false);
  };

  const handleAddCategory = (categoryName) => {
   ...
  };

  const handleCategoryNameChange = (e) => {
    setNewCategoryName(e.target.value);
  };

  return (
    <React.Fragment>
      <Dialog
        fullWidth
        maxWidth={"sm"}
        open={openDialog}
        onClose={handleDialogClose}
      >
        <DialogTitle>Create Video Category</DialogTitle>
        <DialogContent>
          <TextField
            ...
          />
        </DialogContent>
        <DialogActions>
          <Button ...>
            Add Category
          </Button>
          <Button variant="outlined" onClick={handleDialogClose}>
            Close
          </Button>
        </DialogActions>
      </Dialog>
    </React.Fragment>
  );
}

但它不起作用,我想在另一个组件中重用该对话框

我在代码沙盒中有它https://codesandbox.io/s/quizzical-merkle-ivquu?file=/src/App.js

拉斐尔

无缘无故地将 props 复制到 state 是一种反模式,它会导致您的问题。

您有 两个 状态,称为 openDialog(一个在父级中,一个在子级中),并期望它们像相同一样运行.

要更正此问题,请直接在您的组件中使用 props.openDialog,并将 setter 函数也作为 prop 传递下去。然后删除本地状态版本,因为它不会再被使用。

// Pass the setter as well
<CreateCategory openDialog={openDialog} setOpenDialog={setOpenDialog} />
const handleDialogClose = () => {
  props.setOpenDialog(false); // Use the prop.
};
<Dialog
  fullWidth
  maxWidth={"sm"}
  open={props.openDialog} // Use value directly here
  onClose={handleDialogClose}
>

万一这也是以下代码段(您无论如何都应该删除)中的混淆源:

const [openDialog, setOpenDialog] = useState(props.openDialog);

props.openDialog 仅在第一次渲染时使用一次 来初始化状态。将来任何时候 prop 发生变化,状态 都不会 改变以匹配它。这是一个初始值