Ошибка при рендеринге React Portal с помощью Storyshots

Я пытаюсь визуализировать модал с помощью портала, он отлично работает в моем приложении, а также в Storybook, но как только он добавлен в Storyshots, у меня возникают проблемы.

Первая проблема состояла в том, чтобы издеваться над API ReactDOM createPortal. Я сделал это так:

ReactDOM.createPortal = element => element;

Если это не добавлено, я получаю следующую ошибку:

Ошибка: Uncaught [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);
  }
}

Это теперь терпит неудачу с этой ошибкой:

Ошибка: Uncaught [TypeError: Невозможно прочитать свойство 'appendChild' со значением NULL]

Положение указано в фрагменте кода выше.

3 ответа

Вы можете делать 2 разные вещи:

В .storybook добавить новый элемент DOM:

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

Еще одна вещь, которую вы можете сделать, - это имитировать документ, поскольку проблема в том, что вы пытаетесь найти элемент dom, которого не существует.

Другой подход. Поместите в свой установочный файл jest следующее:

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

Как упоминалось здесь, вы можете установить rc-util и добавить следующее либо в начало вашего теста, либо (если вы хотите, чтобы он был глобальным) внутри вашего jest.setup.js (или jest-раздела package.json, если это то, что вы используете).

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

PS. Если вы используете CRA, ваш установочный файл jest находится вsrc/setupTests.js

Другие вопросы по тегам