【问题标题】:react-popper: re-position using scheduleUpdatereact-popper:使用 scheduleUpdate 重新定位
【发布时间】:2019-02-17 02:56:12
【问题描述】:

我使用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)?

【问题讨论】:

    标签: javascript popper.js react-popper


    【解决方案1】:

    我会将 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 是构建应用程序的可怕方式。只需调用状态更改的函数就需要这么多不必要的文件和代码..
    • 我添加了另一种方法
    • 看来您的第一个示例无法运行,因为 ref 无法传递给子组件。 read more
    • 你只需要给它一个不同的名字。 Like innerRef 或者使用 React 的新 forwardRef API
    • 在过去的 4 个小时里我一直在修改这个
    猜你喜欢
    • 2021-02-23
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 2018-05-03
    相关资源
    最近更新 更多