首页 > 解决方案 > 无法在 React Material-UI 中的 useState 中设置值

问题描述

我在 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使用 Dialog open prop 值将传入的哪个设置为 false useState,我在控制台中被点击但 dilaog 没有被调用,如果我手动设置它dialogOpenuseState工作但不是点击,这里发生了什么?

标签: javascriptreactjsreact-hooksmaterial-ui

解决方案


问题是您正在将道具复制到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能够关闭自己(在对话框中很常见),您可以向它传递父级提供的执行此操作的函数。


推荐阅读