我正在尝试将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
];
};
3条答案
按热度按时间bjp0bcyl1#
对话框 Flink 的原因是在
App
中每次渲染时都会创建一个新的对话框组件(作为状态更改的结果)。旧的Dialog
被卸载并被新的Dialog
替换。根据经验,渲染时不应定义组件。
这就是为什么我建议您将自定义对话框组件与
useDialog
挂钩分开:但是,您可以保留
useDialog
内部的一些逻辑并重用它们:关于why returning components from hook can be a bad idea的更多信息。
ocebsuys2#
自定义钩子不是为返回组件而创建的,而是用于创建一个由不同组件共享的公共逻辑。
在你的例子中,我建议你为你的对话框创建一个公共组件。并在你想要的任何地方使用这个组件。就像这样:
有关自定义挂接的详细信息:
https://reactjs.org/docs/hooks-custom.html
webghufk3#
因为我的错误而发现这个问题的人。我使用了一个样式化的对话框,并在功能组件内定义了样式化的对话框。只需将自定义样式放在任何组件之外。