【问题标题】:Styled MUI Drawer not opening when variant is temporary当变体是临时的时,样式化的 MUI 抽屉不会打开
【发布时间】:2021-12-16 20:41:08
【问题描述】:

我创建了一个样式化的MuiDrawer 组件,因此我可以为组件添加一些自定义样式。我想使用temporary 变体,但抽屉没有打开。当我将 Drawer 变体设置为 permanent 时,Drawer 会显示。所以这可能是导致错误的 open 道具的传递。当我使用 MUI 中的默认抽屉组件时,temporary 变体确实有效:

// demo.tsx

import * as React from 'react';
// import Drawer from '@mui/material/Drawer';
import {Drawer} from './styles';
import Button from '@mui/material/Button';

export default function TemporaryDrawer() {
  const [open, setOpen] = React.useState(false);

  const toggleDrawer = () => {
    setOpen(!open);
  };

  return (
    <>
      <Button onClick={toggleDrawer}>Toggle Drawer</Button>
      <Drawer
        variant='temporary'
        open={open}
        onClose={toggleDrawer}
      >
        <p>Drawer</p>
      </Drawer>
    </>
  );
}
// styles.tsx

import {styled} from '@mui/material';
import {Theme, CSSObject} from '@mui/material/styles';
import MuiDrawer from '@mui/material/Drawer';

const drawerWidth = 240;

const openedMixin = (theme: Theme): CSSObject => ({
  backgroundColor: 'green',
  width: drawerWidth,
  transition: theme.transitions.create('width', {
    easing: theme.transitions.easing.sharp,
    duration: theme.transitions.duration.enteringScreen,
  }),
  overflowX: 'hidden',
});

const closedMixin = (theme: Theme): CSSObject => ({
  transition: theme.transitions.create('width', {
    easing: theme.transitions.easing.sharp,
    duration: theme.transitions.duration.leavingScreen,
  }),
  overflowX: 'hidden',
  width: `calc(${theme.spacing(7)} + 1px)`,
  [theme.breakpoints.up('sm')]: {
    width: `calc(${theme.spacing(8)} + 1px)`,
  },
});

export const Drawer = styled(MuiDrawer, {shouldForwardProp: (prop) => prop !== 'open'})(
  ({theme, open}) => ({
    width: drawerWidth,
    flexShrink: 0,
    whiteSpace: 'nowrap',
    boxSizing: 'border-box',
    ...(open && {
      ...openedMixin(theme),
      '& .MuiDrawer-paper': openedMixin(theme),
    }),
    ...(!open && {
      ...closedMixin(theme),
      '& .MuiDrawer-paper': closedMixin(theme),
    }),
  }),
)

https://codesandbox.io/s/temporarydrawer-material-demo-forked-zci40?file=/demo.tsx

【问题讨论】:

    标签: reactjs material-ui


    【解决方案1】:

    虽然@v1s10n_4 的答案是正确的,但我会再解释一下原因。

    purpose of the shouldForwardProp 回调是为了防止 HOC 创建的样式属性泄漏到 DOM 元素导致无效属性错误。您的 Drawer 有一个 open 道具,它是 Dialog 的已知道具,因此您无需担心此处未正确处理该道具:

    const Dialog = (props) => {
      // I know this open prop, so I'm gonna extract it here
      const { open, ...other } = props
    
      // and do some logic with the open prop
    
      // and make sure it is not passed to the Component
      return <Component {...other} />
    }
    

    但是,如果您传递一个不是来自Dialog API 的任意道具,例如bgcolor:

    <Dialog bgcolor='red'
    

    然后会向下传递给DOM元素:

    const Dialog = (props) => {
      const { open, ...other /* other includes the bgcolor prop */ } = props
    
      // logic...
    
      return <Component {...other} />
    }
    

    当您使用styled 创建样式组件时:

    const StyledDialog = styled(Dialog)(...)
    
    <StyledDialog bgcolor='red'
    

    幕后应该是这样的:

    const StyledDialog = (props) => {
      const className = getStyles(props);
    
      return <Dialog {...props} className={className} />
    }
    

    这就是为什么您需要使用shouldForwardProp 来过滤掉与样式相关的道具(不是Dialog 道具),这样它就不会被传递给Dialog:

    const StyledDialog = (props) => {
      const { bgcolor, ...other } = props;
      const className = getStyles(props);
    
      // bgcolor is filtered now.
      return <Dialog {...other} className={className} />
    }
    

    【讨论】:

      【解决方案2】:

      您可以在样式化的 Drawer 定义中删除 {shouldForwardProp: (prop) =&gt; prop !== 'open'}。

      codesandbox

      【讨论】:

      • 你能解释一下为什么吗?
      • 看起来已经像@NearHuscarl explained
      猜你喜欢
      • 2022-12-11
      • 2021-11-06
      • 2019-09-17
      • 1970-01-01
      • 2020-10-07
      • 2017-08-02
      • 1970-01-01
      • 2021-10-05
      • 1970-01-01
      相关资源
      最近更新 更多