react-popper:使用scheduleUpdate重新定位

时间:2018-09-12 12:49:25

标签: javascript popper.js react-popper

点击按钮后,我使用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元素,但是我不知道该如何处理。

如何在scheduleUpdate中公开要调用的特定onDateRangeBtnClick,或者如何在JSX本身中有条件地调用函数(对此,scheduleUpdate)?

1 个答案:

答案 0 :(得分:4)

我将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