1- import React , { Component } from 'react' ;
1+ import React , { useState , useRef , useEffect } from 'react' ;
22import PropTypes from 'prop-types' ;
33
44const SCRIPT_URL = 'https://production-assets.codepen.io/assets/embed/ei.js' ;
5+ const LOAD_STATE = {
6+ booting : '__booting__' ,
7+ error : '__error__' ,
8+ loading : '__loading__' ,
9+ loaded : '__loaded__' ,
10+ } ;
511
6- class ReactCodepen extends Component {
7- state = { loaded : false , loading : true } ;
8-
9- componentDidMount ( ) {
10- this . _mounted = true ;
12+ const ReactCodepen = props => {
13+ const [ loadState , setLoadState ] = useState ( LOAD_STATE . booting ) ;
14+ const [ error , setError ] = useState ( ) ;
15+ const _isMounted = useRef ( false ) ;
1116
17+ const loadScript = ( ) => {
1218 // load the codepen embed script
1319 const script = document . createElement ( 'script' ) ;
1420 script . src = SCRIPT_URL ;
1521 script . async = 1 ;
1622 script . onload = ( ) => {
1723 // do not do anything if the component is already unmounted.
18- if ( ! this . _mounted ) return ;
19-
20- this . setState ( {
21- loaded : true ,
22- loading : false
23- } ) ;
24- }
24+ if ( ! _isMounted . current ) return ;
25+ setLoadState ( LOAD_STATE . loaded ) ;
26+ } ;
2527 script . onerror = ( ) => {
26- if ( ! this . _mounted ) return ;
27-
28- this . setState ( {
29- error : 'Failed to load the pen'
30- } ) ;
31- }
28+ if ( ! _isMounted . current ) return ;
29+ setLoadState ( LOAD_STATE . error ) ;
30+ setError ( 'Failed to load the pen' ) ;
31+ } ;
3232
33+ setLoadState ( LOAD_STATE . loading ) ;
3334 document . body . appendChild ( script ) ;
34- }
35+ } ;
3536
36- componentWillUnmount ( ) {
37- this . _mounted = false ;
38- }
37+ useEffect ( ( ) => {
38+ if ( _isMounted . current === false ) _isMounted . current = true ;
3939
40- render ( ) {
41- if ( ! this . state . loaded && this . props . loader ) {
42- return React . createElement ( this . props . loader , {
43- isLoading : this . state . loading ,
44- error : this . state . error
45- } ) ;
46- } else if ( this . state . loaded ) {
47- const penLink = `https://codepen.io/${ this . props . user } /pen/${ this . props . hash } /` ;
48- const userProfileLink = `https://codepen.io/${ this . props . user } ` ;
40+ loadScript ( ) ;
4941
50- return (
51- < p
52- data-height = { this . props . height }
53- data-theme-id = { this . props . themeId }
54- data-slug-hash = { this . props . hash }
55- data-default-tab = { this . props . defaultTab }
56- data-user = { this . props . user }
57- data-embed-version = { this . props . version }
58- data-pen-title = { this . props . title }
59- data-preview = { this . props . preview }
60- className = "codepen"
61- >
62- See the Pen < a href = { penLink } > { this . props . title } </ a >
63- by { this . props . user } (< a href = { userProfileLink } > @{ this . props . user } </ a > )
64- on < a href = "https://codepen.io" > CodePen</ a > .
65- </ p >
66- ) ;
67- } else {
68- return null ;
69- }
70- }
71- }
42+ return ( ) => ( _isMounted . current = false ) ;
43+ } , [ ] ) ;
44+
45+ const showLoader =
46+ loadState === LOAD_STATE . loading && props . loader !== undefined ;
47+ const visibility = loadState === LOAD_STATE . loaded ? 'visible' : 'hidden' ;
48+ const penLink = `https://codepen.io/${ props . user } /pen/${ props . hash } /` ;
49+ const userProfileLink = `https://codepen.io/${ props . user } ` ;
50+ const styles = { visibility } ;
51+
52+ return (
53+ < React . Fragment >
54+ { showLoader &&
55+ React . createElement ( props . loader , {
56+ isLoading : loadState === LOAD_STATE . loading ,
57+ error,
58+ } ) }
59+ < p
60+ data-height = { props . height }
61+ data-theme-id = { props . themeId }
62+ data-slug-hash = { props . hash }
63+ data-default-tab = { props . defaultTab }
64+ data-user = { props . user }
65+ data-embed-version = { props . version }
66+ data-pen-title = { props . title }
67+ data-preview = { props . preview }
68+ className = "codepen"
69+ style = { styles }
70+ >
71+ See the Pen < a href = { penLink } > { props . title } </ a >
72+ by { props . user } (< a href = { userProfileLink } > @{ props . user } </ a > ) on{ ' ' }
73+ < a href = "https://codepen.io" > CodePen</ a > .
74+ </ p >
75+ </ React . Fragment >
76+ ) ;
77+ } ;
7278
7379ReactCodepen . defaultProps = {
7480 defaultTab : 'css,result' ,
7581 height : 300 ,
7682 preview : true ,
7783 themeId : 'dark' ,
78- version : 2
84+ version : 2 ,
7985} ;
8086
8187ReactCodepen . propTypes = {
8288 defaultTab : PropTypes . string ,
8389 hash : PropTypes . string . isRequired ,
8490 height : PropTypes . number ,
85- loader : PropTypes . oneOfType ( [
86- PropTypes . element ,
87- PropTypes . func
88- ] ) ,
91+ loader : PropTypes . oneOfType ( [ PropTypes . element , PropTypes . func ] ) ,
8992 preview : PropTypes . bool ,
9093 title : PropTypes . string ,
91- themeId : PropTypes . oneOfType ( [
92- PropTypes . string ,
93- PropTypes . number
94- ] ) ,
94+ themeId : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number ] ) ,
9595 user : PropTypes . string . isRequired ,
96- version : PropTypes . number
96+ version : PropTypes . number ,
9797} ;
9898
99- export default ReactCodepen ;
99+ export default ReactCodepen ;
0 commit comments