Как использовать опору типа ref с компонентами meterial-ui, такими как Popover? Пытаюсь понять, как использовать опору 'action' = updatePosition () - PullRequest
1 голос
/ 26 мая 2020

Проблема: я пытаюсь использовать компонент Popover из библиотеки @ material-ui / core и использовать один из реквизитов для изменения размера моего компонента всплывающего окна вручную. Ссылка на документы

Проблема. В описании свойства «действие» указано: «Ссылка на обязательные действия. В настоящее время он поддерживает только действие updatePosition () ». Что меня немного сбивает с толку.

Я пробовал пройти первоначальный PR, но без особой пользы. Также в демоверсии всплывающего окна, я не мог найти его, поэтому разместил здесь.

Можете ли вы показать мне простой код компонента на основе классов, показывающий, как использовать 'императивные' реквизиты ref?

Очень жаль Если это проблема PBKA C, в свою защиту, я уже месяц в React и обнаружил, что это сбивает с толку, поэтому другие люди тоже могут.

1 Ответ

1 голос
/ 26 мая 2020

По этому поводу не так много документации, потому что это не то, что вам обычно понадобится, поскольку обычно вы не должны обновлять вещи императивным способом с помощью React.

При таком подходе вы передаете ссылку в в свойство action, а затем Material-UI позаботится о присвоении объекта (содержащего функцию updatePosition) ссылке (его свойству current). Вот место в коде Popover , где это происходит. Это делается с помощью useImperativeHandle .

В приведенном ниже примере во всплывающем окне есть две кнопки. Одна кнопка перемещает кнопку «Открыть всплывающее окно», императивно добавляя к ней класс. Я обычно не добавляю класс таким образом. Обычно я делаю это декларативно, изменяя состояние, например, как показано здесь: https://codesandbox.io/s/demonstrate-popover-declarative-update-difl4, но использование этого декларативного подхода делает ненужным использование updatePosition (вот почему это обычно не требуется) . Поэтому я только императивно обновляю положение кнопки, чтобы можно было продемонстрировать updatePosition.

Вторая кнопка в Popover вызывает actionRef.current.updatePosition(), чтобы сообщить Popover об обновлении своей позиции на основе текущей позиции ее элемента привязки. . actionRef.current указывает на объект , переданный в useImperativeHandle через Material-UI.

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";

const useStyles = makeStyles(theme => ({
  typography: {
    padding: theme.spacing(2)
  },
  alternateButtonPosition: {
    position: "relative",
    left: 100
  }
}));

export default function SimplePopover() {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);
  const actionRef = React.useRef();
  const handleClick = event => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);
  const id = open ? "simple-popover" : undefined;

  return (
    <div>
      <Button
        aria-describedby={id}
        variant="contained"
        color="primary"
        onClick={handleClick}
      >
        Open Popover
      </Button>
      <Popover
        id={id}
        action={actionRef}
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "left"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "left"
        }}
      >
        <Typography className={classes.typography}>
          The content of the Popover.
          <br />
          <Button
            variant="contained"
            onClick={() => {
              if (
                anchorEl.className.indexOf(classes.alternateButtonPosition) >= 0
              ) {
                anchorEl.className = anchorEl.className.replace(
                  classes.alternateButtonPosition,
                  ""
                );
              } else {
                anchorEl.className += " " + classes.alternateButtonPosition;
              }
            }}
          >
            Move anchor element
          </Button>
          <br />
          <br />
          <Button
            variant="contained"
            onClick={() => actionRef.current.updatePosition()}
          >
            Update Popover Position
          </Button>
        </Typography>
      </Popover>
    </div>
  );
}

Edit Demonstrate Popover updatePosition action

И поскольку вы специально спросили для примера компонента на основе классов, вот тот же пример, преобразованный в класс:

import React from "react";
import { withStyles } from "@material-ui/core/styles";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";

const styles = theme => ({
  typography: {
    padding: theme.spacing(2)
  },
  alternateButtonPosition: {
    position: "relative",
    left: 100
  }
});

class SimplePopover extends React.Component {
  constructor(props) {
    super(props);
    this.state = { anchorEl: null };
    this.actionRef = React.createRef();
  }
  handleClick = event => {
    this.setState({ anchorEl: event.currentTarget });
  };

  handleClose = () => {
    this.setState({ anchorEl: null });
  };
  render() {
    const open = Boolean(this.state.anchorEl);
    const id = open ? "simple-popover" : undefined;
    const anchorEl = this.state.anchorEl;
    return (
      <div>
        <Button
          aria-describedby={id}
          variant="contained"
          color="primary"
          onClick={this.handleClick}
        >
          Open Popover
        </Button>
        <Popover
          id={id}
          action={this.actionRef}
          open={open}
          anchorEl={anchorEl}
          onClose={this.handleClose}
          anchorOrigin={{
            vertical: "bottom",
            horizontal: "left"
          }}
          transformOrigin={{
            vertical: "top",
            horizontal: "left"
          }}
        >
          <Typography className={this.props.classes.typography}>
            The content of the Popover.
            <br />
            <Button
              variant="contained"
              onClick={() => {
                if (
                  anchorEl.className.indexOf(
                    this.props.classes.alternateButtonPosition
                  ) >= 0
                ) {
                  anchorEl.className = anchorEl.className.replace(
                    this.props.classes.alternateButtonPosition,
                    ""
                  );
                } else {
                  anchorEl.className +=
                    " " + this.props.classes.alternateButtonPosition;
                }
              }}
            >
              Move anchor element
            </Button>
            <br />
            <br />
            <Button
              variant="contained"
              onClick={() => this.actionRef.current.updatePosition()}
            >
              Update Popover Position
            </Button>
          </Typography>
        </Popover>
      </div>
    );
  }
}

export default withStyles(styles)(SimplePopover);

Edit Demonstrate Popover updatePosition action

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...