react-popper:使用 scheduleUpdate 重新定位
react-popper: re-position using scheduleUpdate
我正在使用 React-popper 在单击按钮后显示日期选择器元素。
JSX
<Manager>
<Reference>
{({ ref }) => (
<button ref={ref} onClick={this.onDateRangeBtnClick}>click to show</button>
)}
</Reference>
{ReactDOM.createPortal(
<Popper placement="auto-end" >
{({ ref, style, placement, arrowProps, scheduleUpdate }) => (
<div className={`dayPickerOverlay ${this.state.showDatePicker ? "" : "hidden"}`} ref={ref} style={style} data-placement={placement}>
<DateRangePicker />
</div>
)}
</Popper>,
document.querySelector('#root')
)}
</Manager>
单击按钮后调用onDateRangeBtnClick
时,我想通过调用scheduleUpdate
方法重新定位Popper元素,但我不知道如何处理。
如何公开要在 onDateRangeBtnClick
中调用的特定 scheduleUpdate
或者如何在 JSX 本身中有条件地调用函数(scheduleUpdate
)?
我会将 popper 部分拆分成它自己的组件,并利用 React 生命周期挂钩。
在 componentDidUpdate
中你可以检查 open
状态是否改变,并相应地触发 scheduleUpdate
。
// PopperElement.js
export default class PopperElement extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.open && this.props.open !== prevProps.open) {
this.props.scheduleUpdate();
}
}
render() {
return (
<div className={`dayPickerOverlay ${this.state.showDatePicker ? "" : "hidden"}`} ref={ref} style={style} data-placement={placement}>
<DateRangePicker />
</div>
);
}
}
// App.js
<Manager>
<Reference>
{({ ref }) => (
<button ref={ref} onClick={this.onDateRangeBtnClick}>click to show</button>
)}
</Reference>
{ReactDOM.createPortal(
<Popper placement="auto-end">
{({ ref, style, placement, arrowProps, scheduleUpdate }) => (
<PopperElement open={this.state.open} scheduleUpdate={scheduleUpdate} />
)}
</Popper>,
document.querySelector('#root')
)}
</Manager>
如果您更喜欢更简洁的方法,我想我会这样使用 react-powerplug
:
import { Manager, Popper, Reference } from 'react-popper';
import { State } from 'react-powerplug';
const App = () => (
<Manager>
<Popper>
{({ ref, style, scheduleUpdate }) => (
<State initial={{ open: false }} onChange={scheduleUpdate}>
{({ state, setState }) => (
<Fragment>
<Reference>
{({ ref }) => (
<button
ref={ref}
onClick={() => setState({ open: true }})
>click to show</button>
)}
</Reference>
{open && <YourContent ref={ref} style={style} />}
</Fragment>
)}
</State>
)}
</State>
</Manager>
);
为简洁起见,我避免重复 React.createPortal
部分,它应该代替 YourContent
。
我正在使用 React-popper 在单击按钮后显示日期选择器元素。
JSX
<Manager>
<Reference>
{({ ref }) => (
<button ref={ref} onClick={this.onDateRangeBtnClick}>click to show</button>
)}
</Reference>
{ReactDOM.createPortal(
<Popper placement="auto-end" >
{({ ref, style, placement, arrowProps, scheduleUpdate }) => (
<div className={`dayPickerOverlay ${this.state.showDatePicker ? "" : "hidden"}`} ref={ref} style={style} data-placement={placement}>
<DateRangePicker />
</div>
)}
</Popper>,
document.querySelector('#root')
)}
</Manager>
单击按钮后调用onDateRangeBtnClick
时,我想通过调用scheduleUpdate
方法重新定位Popper元素,但我不知道如何处理。
如何公开要在 onDateRangeBtnClick
中调用的特定 scheduleUpdate
或者如何在 JSX 本身中有条件地调用函数(scheduleUpdate
)?
我会将 popper 部分拆分成它自己的组件,并利用 React 生命周期挂钩。
在 componentDidUpdate
中你可以检查 open
状态是否改变,并相应地触发 scheduleUpdate
。
// PopperElement.js
export default class PopperElement extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.open && this.props.open !== prevProps.open) {
this.props.scheduleUpdate();
}
}
render() {
return (
<div className={`dayPickerOverlay ${this.state.showDatePicker ? "" : "hidden"}`} ref={ref} style={style} data-placement={placement}>
<DateRangePicker />
</div>
);
}
}
// App.js
<Manager>
<Reference>
{({ ref }) => (
<button ref={ref} onClick={this.onDateRangeBtnClick}>click to show</button>
)}
</Reference>
{ReactDOM.createPortal(
<Popper placement="auto-end">
{({ ref, style, placement, arrowProps, scheduleUpdate }) => (
<PopperElement open={this.state.open} scheduleUpdate={scheduleUpdate} />
)}
</Popper>,
document.querySelector('#root')
)}
</Manager>
如果您更喜欢更简洁的方法,我想我会这样使用 react-powerplug
:
import { Manager, Popper, Reference } from 'react-popper';
import { State } from 'react-powerplug';
const App = () => (
<Manager>
<Popper>
{({ ref, style, scheduleUpdate }) => (
<State initial={{ open: false }} onChange={scheduleUpdate}>
{({ state, setState }) => (
<Fragment>
<Reference>
{({ ref }) => (
<button
ref={ref}
onClick={() => setState({ open: true }})
>click to show</button>
)}
</Reference>
{open && <YourContent ref={ref} style={style} />}
</Fragment>
)}
</State>
)}
</State>
</Manager>
);
为简洁起见,我避免重复 React.createPortal
部分,它应该代替 YourContent
。