React Material-UI菜单锚被react-window列表破坏

时间:2019-03-16 02:37:35

标签: reactjs material-ui

我在项目中使用Material-UI和react-window。我的问题是,当Material-ui菜单组件位于react-window虚拟列表中时,它不会锚定到所提供的元素。菜单将显示在屏幕的左上角,而不是固定在打开菜单的按钮上。在非虚拟化列表中使用它们时,它会按预期工作。菜单正确锚定在打开它的按钮上。

Here's an example sandbox。沙盒非常特定于我如何使用有问题的组件。

有关如何解决此问题的任何指导?

2 个答案:

答案 0 :(得分:1)

这是您的沙盒的修改版本,可以解决此问题:

Edit BigList menu

这是您在BigList中的初始代码:

const BigList = props => {
  const { height, ...others } = props;
  const importantData = Array(101 - 1)
    .fill()
    .map((_, idx) => 0 + idx);
  const rows = ({ index, style }) => (
    <FancyListItem
      index={index}
      styles={style}
      text="window'd (virtual): "
      {...others}
    />
  );

  return (
    <FixedSizeList
      height={height}
      itemCount={importantData.length}
      itemSize={46}
      outerElementType={List}
    >
      {rows}
    </FixedSizeList>
  );
};

我将其更改为以下内容:

const Row = ({ data, index, style }) => {
  return (
    <FancyListItem
      index={index}
      styles={style}
      text="window'd (virtual): "
      {...data}
    />
  );
};

const BigList = props => {
  const { height, ...others } = props;
  const importantData = Array(101 - 1)
    .fill()
    .map((_, idx) => 0 + idx);
  return (
    <FixedSizeList
      height={height}
      itemCount={importantData.length}
      itemSize={46}
      outerElementType={List}
      itemData={others}
    >
      {Row}
    </FixedSizeList>
  );
};

重要的区别在于,Row现在是一致的组件类型,而不是每次渲染BigList时都会重新定义。在您的初始代码中,BigList的每个渲染都会导致所有FancyListItem元素都被重新挂载,而不仅仅是重新渲染,因为围绕它的表示“行”类型的函数是一个新函数,其中每个{ {1}}。这样的结果是,您传递给BigList的锚元素在Menu试图确定其位置时不再挂载,并且anchorEl.getBoundingClientRect()提供的x,y位置为0 ,0。

您会在react-window文档(https://react-window.now.sh/#/examples/list/fixed-size)中注意到,Menu组件是在Row组件之外定义的,类似于现在的固定版本代码的结构

答案 1 :(得分:0)

瑞安(Ryan)感谢您的回答!它帮助了我!

还有另一种解决方案: 将父组件定义为类组件(而不是功能组件)。

我的问题是我像这样调用'Rows'函数:

 <FixedSizeList
     height={height}
     itemCount={nodes.length}
     itemSize={50}
     width={width}
     overscanCount={10}
    >
        {({ index, style }) => this.renderListItem(nodes[index], style)}
    </FixedSizeList>

此修复与Ryan建议的类似:

render() {
 ...
 return <FixedSizeList
     height={height}
     itemCount={nodes.length}
     itemSize={50}
     width={width}
     overscanCount={10}
     itemData={nodes}
    >
        {this.renderListItem}
    </FixedSizeList>
  }

  renderListItem = ({data,index, style}) => {
    ...
  }

我使用了itemData道具来访问nodes函数内部的renderListItem数组