【问题标题】:preact createPortal renders multiple timespreact createPortal 多次渲染
【发布时间】:2020-09-02 13:24:24
【问题描述】:

我在我的项目中使用 preact(一个小版本的 react)。

在更新到 preactX 版本之前,我使用的是这样的 Modal 组件,它没有任何问题,这就是我的 Modal 组件的样子:

  import { Component } from 'preact';
  import Portal from 'preact-portal';

  export default class Modal extends Component {

  componentWillReceiveProps({ isOpen }) {
    if (this.state.isOpen !== isOpen) {
      this.setState({ isOpen });
    }
  }

  handleClose = () => {
    const { onClose } = this.props;
    this.setState({ isOpen: false });
    onClose && onClose();
  };

  render({ children, closeIcon, isOpen }) {
      return isOpen && (
        <Portal into="body">
          <Wrapper className="notranslate">
            <Overlay />
            <Holder>
              <Close onClick={this.handleClose}>
                <img src={closeIcon || DefaultCloseIcon} alt="Close" />
              </Close>
              {children}
            </Holder>
          </Wrapper>
        </Portal>
      );
   }
 }

升级到 preactX 后,他们放弃了 Portal 组件支持,并将其更改为 createPortal 方法,就像 react 中的方法和问题发生的地方一样,只要 props isOpen 发生变化,它就会呈现,因为模态会打开多次。

这是我使用钩子对带有 createPortal 的模态组件的实现:

import { createPortal, useState, useEffect, memo } from 'preact/compat';

function Modal({ children, onCloseClick, closeIcon, isOpen }) {
  const [isStateOpen, setIsStateOpen] = useState(isOpen);

  useEffect(() => {
    if (isStateOpen != isOpen) {
      setIsStateOpen(isOpen);
    }
    return () => {
      setIsStateOpen(false);
    };
  }, [isOpen]);

  return (
    isStateOpen &&
    createPortal(
      <Wrapper>
        <Overlay />
        <Holder>
          <Close onClick={onCloseClick}>
            <img src={closeIcon || DefaultCloseIcon} alt="Close" />
          </Close>
          {children}
        </Holder>
      </Wrapper>,
      document.body
    )
  );
}

export default memo(Modal);

我正在使用这样的模态组件:

<App>
  <SomeOtherComponents />
  <Modal
    isOpen={hasModalOpen}
    closeIcon={CloseIcon}
    onCloseClick={cancelModal}
  >
    <div>
       some other content here
    </div>
  </Modal>
</App>

我使用 Modal 组件的地方可能会渲染多次,这也使得 Modal 组件渲染,这在我使用 Portal 之前很好,但是当我使用 createPortal 时,createPortal 似乎无法识别 Modal 组件是否已经在dom中与否。

我想在 react 中也会发生同样的情况。

【问题讨论】:

    标签: javascript reactjs preact


    【解决方案1】:

    这不是createPortal 问题,这是您对 Hooks 的使用。 我根据您发布的代码创建了一个演示,并且由于您的 useEffect() 钩子返回的“清理”回调,它不断地重新渲染。该回调是不必要的,删除它可以修复整个演示:

    https://codesandbox.io/s/preact-createportal-renders-multiple-times-32ehe

    【讨论】:

      【解决方案2】:

      我通过在 Modal 组件中添加 shouldComponentUpdate 方法解决了这个问题。

      似乎只要父组件中的任何道具发生变化,即使 isOpen 道具没有改变,该组件也正在渲染。

      shouldComponentUpdate(nextProps) {
          return this.props.isOpen !== nextProps.isOpen;
      }
      

      createPortal 似乎也没有应用浅层渲染,因为旧 Portal 在 preactX 之前的版本中应用了它

      【讨论】:

        猜你喜欢
        • 2017-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 2020-06-17
        • 1970-01-01
        • 1970-01-01
        • 2018-01-13
        相关资源
        最近更新 更多