Ошибка при рендеринге 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