Skip to content

Instantly share code, notes, and snippets.

@paul-phan
Created November 18, 2020 15:04
Show Gist options
  • Save paul-phan/50fd92a124c9114db5665926b703a273 to your computer and use it in GitHub Desktop.
Save paul-phan/50fd92a124c9114db5665926b703a273 to your computer and use it in GitHub Desktop.
import React, {CSSProperties, ReactElement, RefObject, useEffect, useRef, useState} from 'react'
import ReactDOM from 'react-dom'
import styled, {StyleSheetManager} from 'styled-components'
interface ISandboxProps {
style?: CSSProperties
children: ReactElement
getRef?: (ref: RefObject<TODO>) => void
src: string
}
function Sandbox(props: ISandboxProps) {
const {style, children, getRef, src} = props
const [doc, setDoc] = useState<Document | null>(null)
const frame = useRef<HTMLIFrameElement>(null)
const handleIframeLoad = () => {
setDoc(frame.current?.contentDocument ?? null)
}
useEffect(() => {
const currentFrame = frame.current
currentFrame?.addEventListener('load', handleIframeLoad, true)
getRef && getRef(frame)
return () => {
currentFrame?.removeEventListener('load', handleIframeLoad, true)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return <StyledIframe
title={'React Styled Sandbox'}
style={style}
ref={frame}
src={src}
>
{doc ? ReactDOM.createPortal((
<StyleSheetManager
target={doc.head}
>
{children}
</StyleSheetManager>
), doc.body) : null}
</StyledIframe>
}
const StyledIframe = styled.iframe`
height: 100%;
border: none;
width: 100%;
`
export default Sandbox
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment