我已经在Material-UI中创建了一个自定义对话框组件
const CustomDialog = (props) => {
const [dialogOpenState, setOpen] = React.useState(props.dilaogOpenProp);
return (
<>
<CssBaseline />
<Dialog
fullWidth
onClose={() => {}}
open={dialogOpenState}
maxWidth="xs"
sx={{
backdropFilter: "blur(5px)",
}}
>
<DialogTitle>Example Dialog</DialogTitle>
<DialogContent>Example Content Here</DialogContent>
<DialogActions>
<Button>ooooh.</Button>
</DialogActions>
</Dialog>
<Box
sx={{
minHeight: "100vh",
background:
"url(https://source.unsplash.com/random) no-repeat center center",
backgroundSize: "cover",
}}
></Box>
</>
);
}
export default CustomDialog;
我正在尝试使用useState
从另一个组件管理打开关闭
const Minidrawer = props => {
const theme = useTheme();
const { history } = props;
const [open, setOpen] = React.useState(false);
const [dialogOpen,setDialogueOpen] = React.useState(false)
const handleDialogueOpen = () => {
console.log("clicked");
setDialogueOpen(true)
}
return (
<Box sx={{ display: 'flex' }}>
<AppBar position="fixed" open={open}>
<Toolbar>
<Typography variant="h6" noWrap component="div">
COMPANY NAME
</Typography>
<Button onClick={handleDialogueOpen}>Filter</Button>
</Toolbar>
</AppBar>
<CustomDialog dilaogOpenProp={dialogOpen}/>
</Box>
);
}
export default withRouter(Minidrawer);
我试图设置dialogOpen
这是在对话框中通过useState
打开道具值为false,我在控制台被点击,但dilaog没有被调用,也如果我手动设置dialogOpen
在useState
它工作,但没有点击,这是怎么回事?
问题是你复制道具在CustomDialog
状态。这意味着对父进程dilaogOpenProp
的更改将被CustomDialog
忽略。(这通常不是最佳实践,但在一些边缘情况下它是有意义的。)因为你这样做,CustomDialog
只使用初始值,而不是父组件更改后的更新值。下面是一个更简单的例子:
const {useState} = React;
const Child = (props) => {
const [childValue, setChildValue] = useState(props.parentValue);
return <div>
<div><code>props.parentValue = {String(props.parentValue)}</code></div>
<div><code>childValue = {String(childValue)}</code></div>
</div>;
};
const Parent = () => {
const [parentValue, setParentValue] = useState(false);
const toggleParentValue = () => setParentValue(v => !v);
return <div>
<Child parentValue={parentValue} />
<div>
<button onClick={toggleParentValue}>
Toggle <code>parentValue</code>
</button>
</div>
</div>;
};
ReactDOM.render(<Parent />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
您需要将打开/关闭状态存储在父控件中并让父控件控制它,或将打开/关闭状态存储在CustomDialog
中并让CustomDialog
控制它。你不能两者兼顾。
通常这意味着让父进程控制,但是将一个函数传递给子进程,子进程可以用它来告诉父进程发生的变化。例如,如果您需要CustomDialog
能够关闭自己(在对话框中相当常见),您可以将父进程提供的一个函数传递给它。
如果您希望根据父组件提供的prop更新子组件的状态,您可以使用useEffect
。你将道具传递给子组件(React.useState(props.dilaogOpenProp)
)中的useState
,这只在第一次渲染中起作用:
const [dialogOpenState, setOpen] = React.useState(props.dilaogOpenProp);
useEffect(() => {
// update the state every time the prop.dilaogOpenProp dependency changes
setOpen(props.dilaogOpenProp);
}, [props.dilaogOpenProp]);
您必须保持状态更新,使用useState
:
const CustomDialog = ({ dilaogOpenProp }) => {
const [dialogOpenState, setOpen] = React.useState(dilaogOpenProp);
useEffect(() => {
setOpen(props.dialogOpenState);
}, [dilaogOpenProp])
);
}
也可以直接从props获取值
<Dialog open={props.dilaogOpenProp}>
...
</Dialog>