Skip to content

Commit b5edc3b

Browse files
committed
Use innerHTML to set the content for SVG elements
1 parent 7a19635 commit b5edc3b

File tree

2 files changed

+24
-11
lines changed

2 files changed

+24
-11
lines changed

src/index.tsx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ interface InPortalProps {
2424
children: React.ReactNode;
2525
}
2626

27-
export const createPortalNode = <C extends Component<any>>(tagName :string = 'div'): PortalNode<C> => {
27+
export const createPortalNode = <C extends Component<any>>(tagName: string = 'div'): PortalNode<C> => {
2828
let initialProps = {} as ComponentProps<C>;
2929

3030
let parent: Node | undefined;
@@ -44,10 +44,17 @@ export const createPortalNode = <C extends Component<any>>(tagName :string = 'di
4444
}
4545
portalNode.unmount();
4646

47-
newParent.replaceChild(
48-
portalNode,
49-
newPlaceholder
50-
);
47+
// If either the PortalNode or its content is an SVG element, we need to treat it differently
48+
if (portalNode instanceof SVGElement || newPlaceholder instanceof SVGElement) {
49+
// replaceChild does not work well for SVG elements: it will rearrange the dom
50+
// properly but does not render as expected.
51+
(newPlaceholder as HTMLElement).outerHTML = portalNode.innerHTML;
52+
} else {
53+
newParent.replaceChild(
54+
portalNode,
55+
newPlaceholder
56+
);
57+
}
5158

5259
parent = newParent;
5360
lastPlaceholder = newPlaceholder;
@@ -60,10 +67,15 @@ export const createPortalNode = <C extends Component<any>>(tagName :string = 'di
6067
}
6168

6269
if (parent && lastPlaceholder) {
63-
parent.replaceChild(
64-
lastPlaceholder,
65-
portalNode
66-
);
70+
// If either the PortalNode or its content is an SVG element, we need to treat it differently
71+
if (portalNode instanceof SVGElement || lastPlaceholder instanceof SVGElement) {
72+
(portalNode as HTMLElement).innerHTML = '';
73+
} else {
74+
parent.replaceChild(
75+
lastPlaceholder,
76+
portalNode
77+
);
78+
}
6779

6880
parent = undefined;
6981
lastPlaceholder = undefined;
@@ -165,7 +177,8 @@ export class OutPortal<C extends Component<any>> extends React.PureComponent<Out
165177
}
166178

167179
render() {
168-
const { tagName: NodeTagName } = this.props.node;
180+
const { tagName } = this.props.node;
181+
const NodeTagName = tagName.toLowerCase();
169182

170183
// Render a placeholder to the DOM, so we can get a reference into
171184
// our location in the DOM, and swap it out for the portaled node.

stories/index.stories.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ storiesOf('Portals', module)
226226
<Parent />
227227
</div>;
228228
})
229-
.add('Works with SVGs', () => {
229+
.add('works with SVGs', () => {
230230
const portalNode = portals.createPortalNode('text');
231231

232232
// From https://github.com/httptoolkit/react-reverse-portal/issues/2

0 commit comments

Comments
 (0)