Material UI Dialog 转为 Hook 闪烁
Posted
技术标签:
【中文标题】Material UI Dialog 转为 Hook 闪烁【英文标题】:Material UI Dialog turned to Hook flickering 【发布时间】:2020-10-03 09:04:36 【问题描述】:我正在尝试将 Material UI 的对话框变成一个“useDialog”钩子,以便跟踪它自己的打开状态。
不幸的是,我遇到了一个问题,即每当我在层次结构中更新状态时,对话框就会闪烁,我不确定为什么以及如何规避它。我觉得某处需要 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
];
;
【问题讨论】:
【参考方案1】:对话框闪烁的原因是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。
【讨论】:
感谢您的精彩解释。我认为将开闭逻辑封装在一个单独的钩子中没有多大用处,因为它只是一个 useState。我想知道 useCallback 是否可以做一些事情...... 你可以用useCallback
钩子包裹someDialog
的函数并将open
设置为它的依赖,但我不确定它是否是一个好的解决方案。【参考方案2】:
自定义钩子不是为返回组件而设计的,而是用于创建一个由不同组件共享的通用逻辑。
在您的情况下,我建议您为对话框创建一个通用组件。并在任何你想要的地方使用这个组件。像这样:
<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
【讨论】:
以上是关于Material UI Dialog 转为 Hook 闪烁的主要内容,如果未能解决你的问题,请参考以下文章
如何使 Material-UI Dialog 在 React 中工作
Material-UI 的 Dialog 如何允许在对话框后面进行交互?
如何将 Material-table 与 Material-UI Dialog 结合起来? (反应JS)