По этому поводу не так много документации, потому что это не то, что вам обычно понадобится, поскольку обычно вы не должны обновлять вещи императивным способом с помощью 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>
);
}
И поскольку вы специально спросили для примера компонента на основе классов, вот тот же пример, преобразованный в класс:
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);