reactjs - 当变体是临时的时,样式化的 MUI 抽屉不会打开
问题描述
我创建了一个样式MuiDrawer
组件,因此我可以为组件添加一些自定义样式。我想使用该temporary
变体,但抽屉没有打开。当我将 Drawer 变体设置为 Drawer 时permanent
,会显示。所以这可能open
是导致错误的道具的传递。当我使用 MUI 中的默认 Drawer 组件时,该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
解决方案
虽然@v1s10n_4 的答案是正确的,但我会再解释一下原因。
回调的目的shouldForwardProp
是防止 HOC 创建的样式 props 泄漏到 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} />
}
推荐阅读
- python - Python - 逐一处理列表中的所有内容
- javascript - React Hooks 和 useState 的使用
- excel - ssis - 如何参数化excel连接
- angular - 如何在不使用标记的情况下以 angular -typescript 向我的地图添加文本/标签?
- php - Usage of "+" in array - php
- visual-studio - 在 Windows 10 上进行 CUDA 开发需要什么?
- java - Cas服务器和Web服务认证(服务票证)
- javascript - 获取 DropdownItem 的标签或值以将文本值设置为 DropdownToggle
- java - 致命异常:主要,膨胀类片段时出错,android.view.InflateException
- git - git:将两个分支与一个分支中的秘密文件合并