3

单击按钮后,我正在使用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,我想通过调用方法重新定位 Popper 元素scheduleUpdate,但我不知道如何处理。

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

4

1 回答 1

7

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

于 2018-09-12T14:54:20.517 回答