使用 Storyshot 渲染 React Portal 时出错

Posted

技术标签:

【中文标题】使用 Storyshot 渲染 React Portal 时出错【英文标题】:Error when rendering React Portal with Storyshots 【发布时间】:2019-02-09 07:56:02 【问题描述】:

我正在尝试使用门户呈现模式,它在我的应用程序以及 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]

上面代码sn-p中所指示的位置。

【问题讨论】:

以防万一,也许这是一个愚蠢的评论,但只是为了确定:在您的标记(html)中,您是否有一个 id = 'modal-root' 的元素? 你得到答案了吗?很高兴更新和关闭这个问题 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

你可以做两件事:

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

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

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

【讨论】:

【参考方案3】:

如here 所述,您可以安装rc-util 并将以下内容添加到您的测试顶部或(如果您希望它是全局的)在您的 jest.setup.js(或 package.json jest 部分,如果是的话)你用什么)。

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

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

【讨论】:

以上是关于使用 Storyshot 渲染 React Portal 时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何正确实现 React 子域?

React学习:条件渲染

react怎么渲染canvas

React 使用服务器端渲染还是客户端渲染?

使用 WebWorkers 渲染 React 组件

react 在模板中渲染 html 字符串