reactjs - 是否可以在自己的组件中使用 ListContext?
问题描述
我想使用dense
ListContext 的属性来更改 ListItemIcon 字体大小。当我尝试将组件包装在自己的组件中并导入和使用上下文时,上下文是空的。该组件在内部用作 List/ListItem,因此它通常应该具有一些值。我想这是因为 ListContext 仅在内部使用还是我错了?如果我不能使用它,有什么可能的解决方案?
import React from 'react';
import MuiListItemIcon, {
ListItemIconProps as MuiListItemIconProps,
} from '@material-ui/core/ListItemIcon';
import ListContext from '@material-ui/core/List/ListContext';
const ListItemIcon: React.ForwardRefExoticComponent<MuiListItemIconProps> = React.forwardRef(
(props, ref) => {
const { children, ...other } = props;
const context = React.useContext(ListContext);
return (
<MuiListItemIcon ref={ref} {...other}>
{context.dense ? React.cloneElement(children, { fontSize: 'small' }) : children}
</MuiListItemIcon>
);
},
);
export default ListItemIcon;
// ...
<List dense>
<ListItem>
<ListItemIcon>
<IcoCreate />
<ListItemIcon>
</ListItem>
<ListItemText primary="Hello world!">
<List>
// ...
我希望上下文的dense
属性设置为true
,但实际值为空。
解决方案
ListContext
被认为是私有的。在最小化捆绑包大小指南中,您可以找到以下内容:
请注意,我们仅支持一级和二级导入。以下任何内容都被认为是私有的,并且可能导致您的包中的模块重复。
您的导入ListContext
是三级导入(List
将是二级):
import ListContext from '@material-ui/core/List/ListContext';
虽然导入它“有效”,但您导入的是副本ListContext
而不是使用的相同副本,List
这会导致它成为唯一的上下文类型,因此不受ListContext
Material-UI 内部设置的影响。
有几种方法可以实现您想要的结果,即根据它是否在密集列表中动态调整图标字体大小:
- 使用您在包装器中使用的自己的上下文类型创建您自己的
List
包装器(除了您的包装器) 。ListItemIcon
ListItemIcon
- 使用 CSS(根据 prop 在内部模仿 SvgIcon 所做的)来更改字体大小,而不是使用
fontSize
下面示例中所示的属性。
import React from "react";
import ReactDOM from "react-dom";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import CreateIcon from "@material-ui/icons/Create";
import { withStyles } from "@material-ui/core/styles";
const SmallIconIfDense = withStyles(theme => ({
root: {
".MuiListItem-dense & .MuiSvgIcon-root": {
fontSize: theme.typography.pxToRem(20)
}
}
}))(ListItemIcon);
function App() {
return (
<>
<List dense>
<ListItem>
<SmallIconIfDense>
<CreateIcon />
</SmallIconIfDense>
<ListItemText primary="Hello dense list!" />
</ListItem>
<ListItem>
<SmallIconIfDense>
<CreateIcon />
</SmallIconIfDense>
<ListItemText primary="Hello second list item!" />
</ListItem>
</List>
<List>
<ListItem>
<SmallIconIfDense>
<CreateIcon />
</SmallIconIfDense>
<ListItemText primary="Hello non-dense list!" />
</ListItem>
<ListItem>
<SmallIconIfDense>
<CreateIcon />
</SmallIconIfDense>
<ListItemText primary="Hello second list item!" />
</ListItem>
</List>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
推荐阅读
- python - 使用systemd在启动时运行.py文件后如何通过SSH访问Raspberrypi?
- r - 在 drc::drm() 中使用限制约束计算 IC50 的最佳方法
- javascript - Three.js:使用点从高度图采样
- docker - 有谁知道如何将 docker 容器指向 ngrok?
- reactjs - React-js 项目部署失败。“服务”未被识别为内部或外部命令
- html - 任何适用指令均未提供 FormControl
- generics - 使用 IMediator .Net Core 2 注入通用命令处理程序时出错
- html - 包含多个重叠 div 的匹配容器
- r - Tidyeval 拼接运算符!!!ggplot 的 aes 失败
- gridview - 如何在项目构建器 gridview.builder Flutter Firebase Stream Builder 中跳过构建