Я бы разделил поппер часть на ее собственный компонент и использовал бы преимущества крючков жизненного цикла 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
.