React/MUI Popover与anchorPosition的位置不正确 [英] React/MUI Popover positioning incorrectly with anchorPosition

查看:66
本文介绍了React/MUI Popover与anchorPosition的位置不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 react-window 列表元素中使用React/MUI Popover无法将Popover正确定位-它总是在窗口的左上角缠绕(组件无法在文档中的锚元素[ anchorEl 上执行getBoundingClientRctd()]).

I'm using a React/MUI Popover inside a react-window List element and am unable to get the Popover to position correctly -- it always winds up in the top left corner of the window (the component is unable to perform a getBoundingClientRctd() on the anchor element [anchorEl in the docs]).

因此,为了暂时解决该问题,我决定使用 anchorPosition 参数,该参数允许设置绝对位置-在我的情况下,仅位于窗口的中间.那也不行.

So to get around that problem temporarily, I decided to use the anchorPosition parameter which allows to set an absolute position -- in my case, just the middle of the window. That's not working either.

我已经查看了Chrome DevTools中的值,并且一切似乎都正常(即,使用时确实得到了anchorEl;获得了有效的positionLeft/Top值;等等...

I've reviewed the values in Chrome DevTools and everything seems to be OK (i.e., I do get an anchorEl when I'm using that; I get valid positionLeft/Top values; etc...

可能很简单,希望有人能指出我做错了.

Probably something really simple and hoping someone can point out what I did wrong.

已解决方案的关键要素

  1. Row 组件必须在包含组件之外定义.
  2. < List> 组件具有 itemData 属性,该属性用于将自定义数据传递到 Row .
  1. Row component must be defined outside of the containing component.
  2. the <List> component has an itemData attribute which is used to pass custom data to Row.

已编辑以添加反应窗口列表渲染器.

这是基本设置:

  renderPopover(template, itemId) {
    const { anchorEl, anchorId } = this.state;
    const { classes } = this.props;
    const open = Boolean(anchorEl) && anchorId === itemId;
    const bgColor = '#babaef';
    const { innerHeight, innerWidth } = window;
    const positionLeft = innerWidth / 2;
    const positionTop = innerHeight / 2;
    console.log(`renderPopover: ${positionLeft} / ${positionTop}`);
      <Popover
        id="simple-popper"
        open={open}
        style={{ color: 'Black' }}
        anchorEl={anchorEl}
        onClose={event => this.handlePopoverClose(event)}
        anchorPosition={{ left: {positionLeft}, top: {positionTop} }}
        anchorReference="anchorPosition"
      >
        <Typography style={{ backgroundColor: bgColor }} className={classes.typography}>
          {this.renderScheduleElements(template, itemId)}
        </Typography>
      </Popover>
    );
  }

按钮元素渲染器

 renderScheduleComponent(template, itemId) {
    const { anchorEl, anchorId } = this.state;
    const open = Boolean(anchorEl) && anchorId === itemId;
    const { classes } = this.props;
    const id = open ? 'simple-popper' : undefined;
    return (
      <Grid key={itemId} item>
        <Paper className={classes.paper}>
          <div style={{ padding: '4px' }}>
            <Button
              NO_ref={itemId}
              NODE_ref={(node) => this.buttonRef = node}
              id={itemId}
              name={itemId}
              aria-owns={id}
              aria-haspopup="true"
              variant="outlined"
              color="primary"
              style={{
                fontWeight: 'bold',
                padding: '8px',
                margin: 'auto',
                display: 'block',
                width: '100%',
              }}
              onClick={event => this.handlePopoverClick(event, itemId)}
            >
              {template.templateName}
            </Button>
            {(this.renderPopover).call(this, template, itemId)}
          </div>
        </Paper>
      </Grid>
    );
  }

点击事件处理程序

  handlePopoverClick(event, id) {
  event.preventDefault();
    console.log(`handlePopoverClick : ${event.currentTarget.name}`);
    this.setState({
      anchorEl: event.currentTarget,
      anchorId: id,
    });
  }

反应窗口列表渲染器

  renderScheduleColumn(columnData) {
    const { classes } = this.props;
    const { scheduleDate, scheduleTemplates } = columnData;
    this.scheduleTemplates = scheduleTemplates;

    const Row = ({ index, style }) => {
      return (
        <div className={index % 2 ? "ListItemOdd" : "ListItemEven"} style={style}>
          {this.renderScheduleComponent(scheduleTemplates[index], `${scheduleDate}:${index}`)}
        </div>
      );
    }

    const { columnHeight, columnWidth } = this.state;
    return (
      <Grid id={scheduleDate} key={scheduleDate} item>
        <Paper className={classes.paper}>
          <div style={{ width: '100%', textAlign: 'center' }}>
            <Typography variant="h6" style={{ padding: '24px', color: 'white', backgroundColor: '#3f51b5' }}>
              {scheduleDate}
            </Typography>
          </div>
          <List
            className="List"
            height={columnHeight}
            itemCount={scheduleTemplates.length}
            itemSize={50}
            width={columnWidth}
          >
            {Row}
          </List>
        </Paper>
      </Grid>
    );
  }

推荐答案

它看起来像是与此处类似的问题:

It looks like a similar problem as here: React Material-UI menu anchor broken by react-window list.

您应该将 Row 函数的定义移出 renderScheduleColumn ,以便它是一致的类型.这也需要移动/重做 renderScheduleComponent .您可以使用 List 上的 itemData 属性将信息传递给 Row.

You should move the definition of your Row function out of renderScheduleColumn so that it is a consistent type. This will require moving/reworking renderScheduleComponent as well. You can use the itemData property on the List to pass information to the Row.

这篇关于React/MUI Popover与anchorPosition的位置不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆