首页 > 解决方案 > 是否可以在自己的组件中使用 ListContext?

问题描述

我想使用denseListContext 的属性来更改 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,但实际值为空。

标签: reactjsmaterial-ui

解决方案


ListContext被认为是私有的。在最小化捆绑包大小指南中,您可以找到以下内容:

请注意,我们仅支持一级和二级导入。以下任何内容都被认为是私有的,并且可能导致您的包中的模块重复。

您的导入ListContext是三级导入(List将是二级):

import ListContext from '@material-ui/core/List/ListContext';

虽然导入它“有效”,但您导入的是副本ListContext而不是使用的相同副本,List这会导致它成为唯一的上下文类型,因此不受ListContextMaterial-UI 内部设置的影响。

有几种方法可以实现您想要的结果,即根据它是否在密集列表中动态调整图标字体大小:

  • 使用您在包装器中使用的自己的上下文类型创建您自己的List包装器(除了您的包装器) 。ListItemIconListItemIcon
  • 使用 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);

如果在密集列表中,则编辑小图标


推荐阅读