Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Use React portals to render inside shadow dom and iframes
class Frame extends Component {
componentDidMount() {
this.iframeHead = this.node.contentDocument.head
this.iframeRoot = this.node.contentDocument.body
this.forceUpdate()
}
render() {
const { children, head, ...rest } = this.props
return (
<iframe {...rest} ref={node => (this.node = node)}>
{this.iframeHead && ReactDOM.createPortal(head, this.iframeHead)}
{this.iframeRoot && ReactDOM.createPortal(children, this.iframeRoot)}
</iframe>
)
}
}
<Frame head={<title>Hello World</title>}>
<h1>Hello World</h1>
</Frame>
class Shadow extends Component {
componentDidMount() {
this.shadowRoot = this.node.attachShadow({ mode: this.props.mode })
this.forceUpdate()
}
render() {
const { children, ...rest } = this.props
return (
<div {...rest} ref={node => (this.node = node)}>
{this.shadowRoot && ReactDOM.createPortal(children, this.shadowRoot)}
</div>
)
}
}
<Shadow mode="open">
<h1>Hello World</h1>
</Shadow>
@lijunle

This comment has been minimized.

Copy link

@lijunle lijunle commented Dec 14, 2017

Should I use state instead of class variables to be react-style?

@jjenzz

This comment has been minimized.

Copy link

@jjenzz jjenzz commented Apr 11, 2018

I'm trying this in Firefox 59.0.2 and the content appears for a split second and then disappears: https://codesandbox.io/s/4j72vl564x

Does anyone know how to solve this?

UPDATE: Fixed https://codesandbox.io/s/4lr7oxxrl7 🙂

@bury-source

This comment has been minimized.

Copy link

@bury-source bury-source commented Sep 7, 2018

how can I insert two <link> into iframeHead? React only accept one child element?

@anothertempore

This comment has been minimized.

Copy link

@anothertempore anothertempore commented Jan 4, 2019

It's helpful! thanks.

@o-t-w

This comment has been minimized.

Copy link

@o-t-w o-t-w commented Jan 13, 2019

How do you add styles into the shadow DOM example?

@herodrigues

This comment has been minimized.

Copy link

@herodrigues herodrigues commented Feb 27, 2019

Add this.shadowRoot.appendChild(this.props.style) after attaching the shadow. Pass a style element as a prop.

@LinZap

This comment has been minimized.

Copy link

@LinZap LinZap commented Jul 30, 2019

I'm trying this in Firefox 59.0.2 and the content appears for a split second and then disappears: https://codesandbox.io/s/4j72vl564x

Does anyone know how to solve this?

UPDATE: Fixed https://codesandbox.io/s/4lr7oxxrl7 🙂

I think get correct <body> node in <iframe> must be at the onLoad event

Thank you so much 🙂

@lucasterra

This comment has been minimized.

Copy link

@lucasterra lucasterra commented Mar 11, 2020

Using React Hooks and createPortal:
https://codesandbox.io/s/iframe-demo-zd0b0

@saliyawi

This comment has been minimized.

Copy link

@saliyawi saliyawi commented Aug 7, 2020

This one really helpful, Thanks

@luisincrespo

This comment has been minimized.

Copy link

@luisincrespo luisincrespo commented Jan 27, 2021

I'm trying this in Firefox 59.0.2 and the content appears for a split second and then disappears: https://codesandbox.io/s/4j72vl564x
Does anyone know how to solve this?
UPDATE: Fixed https://codesandbox.io/s/4lr7oxxrl7 🙂

I think get correct <body> node in <iframe> must be at the onLoad event

Thank you so much 🙂

This worked for me as well, thanks!

@bilobom

This comment has been minimized.

Copy link

@bilobom bilobom commented Feb 14, 2021

I used the shadow dom to isolate Styles here is the functional component version of it:

const ShadowWrapper = (props) => {
  const { children, mode = "open", ...rest } = props;

  const ref = useRef();
  const [shadowRoot, setShadowRoot] = useState(null);

  useEffect(() => {
    setShadowRoot(ref.current.attachShadow({ mode }));
  }, []);

  return (
    <div {...rest} ref={ref}>
      {shadowRoot && ReactDOM.createPortal(children, shadowRoot)}
    </div>
  );
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment