preact createPortal 渲染多次

preact createPortal renders multiple times

我在我的项目中使用了 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 or not.

我想同样的事情也会发生在反应中。

这不是 createPortal 问题,而是您对 Hooks 的使用。 我根据您发布的代码创建了一个演示,由于从您的 useEffect() 挂钩返回的 "cleanup" 回调,它一直在重新呈现。该回调是不必要的,删除它可以修复整个演示:

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

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

似乎只要父组件中的任何 prop 发生变化,即使 isOpen prop 没有改变,组件也会渲染。

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

createPortal 似乎也没有应用浅层渲染,因为旧的 Portal 在 preactX

之前的版本中应用了它