Skip to content

Commit d36afef

Browse files
committed
fix the broken embed
use the latest hooks api
1 parent cfd867f commit d36afef

4 files changed

Lines changed: 150 additions & 945 deletions

File tree

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"react",
55
"codepen"
66
],
7-
"version": "0.1.0",
7+
"version": "1.0.0",
88
"description": "React component to embed codepen project",
99
"main": "lib/index.js",
1010
"repository": {
@@ -29,11 +29,11 @@
2929
"babel-preset-react": "^6.24.1",
3030
"flow-bin": "^0.41.0",
3131
"jest": "^19.0.2",
32-
"react": "^16.0.0",
33-
"react-dom": "^16.0.0",
32+
"react": "^16.8.0",
33+
"react-dom": "^16.8.0",
3434
"react-test-renderer": "^16.0.0"
3535
},
3636
"peerDependencies": {
37-
"react": "*"
37+
"react": "^16.8.0"
3838
}
3939
}

prettier.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
trailingComma: 'es5',
3+
tabWidth: 2,
4+
semi: true,
5+
singleQuote: true,
6+
};

src/index.js

Lines changed: 65 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,99 @@
1-
import React, { Component } from 'react';
1+
import React, { useState, useRef, useEffect } from 'react';
22
import PropTypes from 'prop-types';
33

44
const 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

7379
ReactCodepen.defaultProps = {
7480
defaultTab: 'css,result',
7581
height: 300,
7682
preview: true,
7783
themeId: 'dark',
78-
version: 2
84+
version: 2,
7985
};
8086

8187
ReactCodepen.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

Comments
 (0)