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