是否可以在自己的组件中使用ListContext?

时间:2019-10-29 09:47:14

标签: reactjs material-ui

我想使用ListContext的dense属性来更改ListItemIcon fontSize。当我尝试自己包装组件并导入并使用上下文时,上下文为空。该组件在内部用作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,但实际值为空。

1 个答案:

答案 0 :(得分:0)

ListContext被视为私有。在Minimizing Bundle Size guide中,您可以找到以下内容:

  

请注意,我们仅支持第一级和第二级导入。以下任何内容都被视为私有内容,可能会导致捆绑软件中的模块重复。

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

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

虽然它可以“导入”,但您正在导入ListContext的副本,而不是List使用的副本,这导致它是唯一的上下文类型,因此不受此影响Material-UI内部的ListContext的设置。

有几种方法可以根据是否在密集列表中来动态调整图标字体大小,从而达到预期效果:

  • 使用在List包装器中使用的上下文类型,创建自己的ListItemIcon包装器(除ListItemIcon包装器之外)。
  • 使用CSS(模仿SvgIcon does internally based on the prop)来更改字体大小,而不是使用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);

Edit Small icon if in dense list