7

我正在尝试使用门户呈现模式,它在我的应用程序以及 Storybook 中都可以正常工作,但是一旦将其添加到 Storyshots 中,我就会遇到问题。

第一个问题是模拟 ReactDOM 的 createPortal API。我是这样做的:

ReactDOM.createPortal = element => element;

如果不添加,我会收到以下错误:

错误:未捕获 [TypeError:parentInstance.children.indexOf 不是函数]

我找到了这个解决方案React Portal Error

这解决了这个问题,但是当组件使用门户时,它会在尝试附加子项时失败。它没有找到“modal-root”组件,因此无法附加元素。我不知道如何克服这一点。

我的门户看起来与 React 网站上的示例几乎相同:

import React from 'react';
import { createPortal } from 'react-dom';
import { node } from 'prop-types';

class Portal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // !!!!!!!fails here !!!!!!!!!
    document.getElementById('modal-root').appendChild(this.el);
  }

  componentWillUnmount() {
    document.getElementById('modal-root').removeChild(this.el);
  }

  render() {
    return createPortal(this.props.children, this.el);
  }
}

它现在失败并出现此错误:

错误:未捕获 [TypeError:无法读取属性 'appendChild' of null]

上面代码片段中指示的位置。

4

3 回答 3

5

你可以做两件不同的事情:

添加.storybook一个新的 DOM 元素:

let modalRoot = document.createElement("div")
modalRoot.setAttribute("id", "modal-root")
document.querySelector("body")!.appendChild(modalRoot)

您还可以做的另一件事是模拟文档,因为问题是您试图找到一个不存在的 dom 元素。

于 2020-03-03T08:44:16.360 回答
0

另一种方法。将以下内容放入您的 jest 设置文件中:

jest.mock('react-dom', () => {
  const original = jest.requireActual('react-dom');
  return {
    ...original,
    createPortal: node => node,
  };
});

于 2021-04-20T07:35:28.160 回答
0

正如这里提到的,您可以安装rc-util并将以下内容添加到您的测试顶部或(如果您希望它是全局的)在您的 jest.setup.js (或 package.json jest 部分,如果这是您使用的)中。

jest.mock('rc-util/lib/Portal')

PS。如果您使用CRA,您的 jest 设置文件位于src/setupTests.js

于 2019-07-05T12:01:08.513 回答