reactjs “材质UI”对话框变为“挂钩” Flink

wyyhbhjk  于 2022-12-12  发布在  React
关注(0)|答案(3)|浏览(140)

我正在尝试将Material UI的对话框转换为“useDialog”挂钩,以便它跟踪自己的打开状态。
不幸的是,我遇到了一个问题,每当我更新一个更高层次的状态时,对话框就会 Flink ,我不知道为什么以及如何避免它。我感觉在某个地方需要一个useRef,但我不确定。下面是一个重现的最小示例:https://codesandbox.io/s/flickering-dialog-minimal-example-ehruf?file=/src/App.js
还有问题中的代码:

import React, { useState } from "react";
    import {
      Button,
      Dialog,
      DialogActions,
      DialogContent,
      DialogTitle
    } from "@material-ui/core";

    export default function App() {
      const [openDialog, Dialog] = useDialog();
      const [counter, setCounter] = useState(0);

      return (
        <div>
          <Dialog title="Hello">
            <div>{counter}</div>
            <button onClick={() => setCounter(counter => counter + 1)}>
              Increase
            </button>
          </Dialog>
          <button onClick={openDialog}>Open dialog</button>
        </div>
      );
    }

    const useDialog = () => {
      const [open, setOpen] = useState(false);
      const handleClose = () => {
        setOpen(false);
      };

      const someDialog = ({ title, children }) => {
        return (
          <Dialog open={open} onClose={handleClose}>
            <DialogTitle>{title}</DialogTitle>
            <DialogContent>{children}</DialogContent>
            <DialogActions>
              <Button onClick={handleClose} color="primary">
                Close
              </Button>
            </DialogActions>
          </Dialog>
        );
      };
      return [
        () => {
          setOpen(true);
        },
        someDialog
      ];
    };
bjp0bcyl

bjp0bcyl1#

对话框 Flink 的原因是在App中每次渲染时都会创建一个新的对话框组件(作为状态更改的结果)。旧的Dialog被卸载并被新的Dialog替换。
根据经验,渲染时不应定义组件。
这就是为什么我建议您将自定义对话框组件与useDialog挂钩分开:

const MyDialog = ({ open, handleClose, title, children }) => {
  return (
    <Dialog open={open} onClose={handleClose}>
      <DialogTitle>{title}</DialogTitle>
      <DialogContent>{children}</DialogContent>
      <DialogActions>
        <Button onClick={handleClose} color="primary">
          Close
        </Button>
      </DialogActions>
    </Dialog>
  );
};

但是,您可以保留useDialog内部的一些逻辑并重用它们:

const useDialog = () => {
  const [open, setOpen] = useState(false);
  const openDialog = () => {
    setOpen(true);
  };
  const handleClose = () => {
    setOpen(false);
  };
  const props = {
    open,
    handleClose
  };
  return [openDialog, props];
};

关于why returning components from hook can be a bad idea的更多信息。

ocebsuys

ocebsuys2#

自定义钩子不是为返回组件而创建的,而是用于创建一个由不同组件共享的公共逻辑。
在你的例子中,我建议你为你的对话框创建一个公共组件。并在你想要的任何地方使用这个组件。就像这样:

<CustomDialog open={open}>
// Your jsx here
</CustomDialog>

const CustomDialog = ({children}) => {
return <Dialog open={open} onClose={handleClose}>
            <DialogTitle>{title}</DialogTitle>
            <DialogContent>{children}</DialogContent>
            <DialogActions>
              <Button onClick={handleClose} color="primary">
                Close
              </Button>
            </DialogActions>
          </Dialog>
}

有关自定义挂接的详细信息:
https://reactjs.org/docs/hooks-custom.html

webghufk

webghufk3#

因为我的错误而发现这个问题的人。我使用了一个样式化的对话框,并在功能组件内定义了样式化的对话框。只需将自定义样式放在任何组件之外。

// This needed to be outstide of the BetterDialog component
const CustomDialog = styled(Dialog)({
  "&    .MuiDialog-paper": {
    zIndex: 90
  }
})

...

function BetterDialog(props: BetterDialogProps) {
...

相关问题