无法在 React Material-UI 中的 useState 中设置值

Posted

技术标签:

【中文标题】无法在 React Material-UI 中的 useState 中设置值【英文标题】:Not able to setValue in useState in React Material-UI 【发布时间】:2021-12-02 16:24:54 【问题描述】:

我在 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);

我正在尝试使用 useState 将在对话框中传递的 dialogOpen 属性值设置为 false,我在控制台中被点击但 dilaog 没有被调用,如果我手动设置 dialogOpenuseState 它的工作但不是点击,这里发生了什么?

【问题讨论】:

dilaogOpenProp 变量中有错字。 【参考方案1】:

问题是您将道具复制到CustomDialog 中的状态。这意味着CustomDialog 会忽略父项中对dilaogOpenProp 的更改。 (这通常是 not best practice,但在某些极端情况下它可能有意义。)既然你这样做了,CustomDialog 只使用该道具的 initial 值,而不是更新后的值当您的父组件更改它时。下面是一个更简单的示例:

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 能够自行关闭(在对话框中很常见),您可以将其传递给父级提供的执行此操作的函数。

【讨论】:

【参考方案2】:

如果您希望子组件的状态根据父组件提供的道具更新,您可以使用useEffect。您将 prop 传递给子组件 (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]);

【讨论】:

【参考方案3】:

你必须保持状态更新,使用useState:

const CustomDialog = ( dilaogOpenProp ) => 
  const [dialogOpenState, setOpen] = React.useState(dilaogOpenProp);

    useEffect(() => 
        setOpen(props.dialogOpenState);
    , [dilaogOpenProp])
  );

你也可以直接从props中获取值

<Dialog open=props.dilaogOpenProp>
    ...
</Dialog>

【讨论】:

以上是关于无法在 React Material-UI 中的 useState 中设置值的主要内容,如果未能解决你的问题,请参考以下文章

生产/构建中的 Material-UI 渲染错误

如何使 Material-UI Dialog 在 React 中工作

TS 表达式生成的联合类型过于复杂,无法用 Material-UI 和 @react-three/fiber 表示

在 Material-ui 中使用 mixins 自定义 React 中的组件

获取 React Material-UI Autocomplete 中的值

./src/App.js 模块未找到:无法解析 xxx 中的“@material-ui/data-grid”