Skip to content

Commit edba11c

Browse files
authored
Merge pull request #226 from FormidableLabs/issue/220-no-component-will-mount
Move LiveProvider to hooks, fixes #220
2 parents 1b93fc5 + b9385d9 commit edba11c

File tree

7 files changed

+96
-104
lines changed

7 files changed

+96
-104
lines changed

demo/next.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ module.exports = {
44
reactStrictMode: true,
55
webpack: config => {
66
config.resolve.alias['react-live'] = path.resolve('../');
7+
config.resolve.alias.react = path.resolve('./node_modules/react');
8+
config.resolve.alias['react-dom'] = path.resolve('./node_modules/react-dom');
79

810
return config;
911
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
"eslint-plugin-react": "^7.7.0",
5252
"jest": "^22.2.1",
5353
"prettier": "^1.17.0",
54-
"react": "^16.2.0",
55-
"react-dom": "^16.2.0",
54+
"react": "^16.8.0",
55+
"react-dom": "^16.8.0",
5656
"rollup": "^0.55.3",
5757
"rollup-plugin-babel": "^3.0.3",
5858
"rollup-plugin-commonjs": "^8.3.0",

src/components/Editor/index.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { theme as liveTheme } from '../../constants/theme';
77
class CodeEditor extends Component {
88
static propTypes = {
99
code: PropTypes.string,
10-
disabled: PropTypes.boolean,
10+
disabled: PropTypes.bool,
1111
language: PropTypes.string,
1212
onChange: PropTypes.func,
1313
style: PropTypes.object,
@@ -58,15 +58,7 @@ class CodeEditor extends Component {
5858
);
5959

6060
render() {
61-
// eslint-disable-next-line no-unused-vars
62-
const {
63-
style,
64-
code: _code,
65-
onChange,
66-
language,
67-
theme,
68-
...rest
69-
} = this.props;
61+
const { style, theme, ...rest } = this.props;
7062
const { code } = this.state;
7163

7264
const baseTheme =

src/components/Live/LivePreview.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import PropTypes from 'prop-types';
23
import LiveContext from './LiveContext';
34

45
function LivePreview({ Component, ...rest }) {
@@ -11,6 +12,10 @@ function LivePreview({ Component, ...rest }) {
1112
);
1213
}
1314

15+
LivePreview.propTypes = {
16+
Component: PropTypes.node
17+
};
18+
1419
LivePreview.defaultProps = {
1520
Component: 'div'
1621
};
Lines changed: 65 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,89 @@
1-
import React, { Component } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import PropTypes from 'prop-types';
33

44
import LiveContext from './LiveContext';
55
import { generateElement, renderElementAsync } from '../../utils/transpile';
66

7-
export default class LiveProvider extends Component {
8-
static defaultProps = {
9-
code: '',
10-
noInline: false,
11-
language: 'jsx',
12-
disabled: false
13-
};
7+
function LiveProvider({
8+
children,
9+
code,
10+
language,
11+
theme,
12+
disabled,
13+
scope,
14+
transformCode,
15+
noInline = false
16+
}) {
17+
const [state, setState] = useState({
18+
error: undefined,
19+
element: undefined
20+
});
1421

15-
static propTypes = {
16-
children: PropTypes.children,
17-
code: PropTypes.string,
18-
disabled: PropTypes.bool,
19-
language: PropTypes.string,
20-
noInline: PropTypes.bool,
21-
scope: PropTypes.object,
22-
theme: PropTypes.object,
23-
transformCode: PropTypes.node
24-
};
25-
26-
// eslint-disable-next-line camelcase
27-
UNSAFE_componentWillMount() {
28-
const { code, scope, transformCode, noInline } = this.props;
29-
30-
this.transpile({ code, scope, transformCode, noInline });
31-
}
32-
33-
componentDidUpdate({
34-
code: prevCode,
35-
scope: prevScope,
36-
noInline: prevNoInline,
37-
transformCode: prevTransformCode
38-
}) {
39-
const { code, scope, noInline, transformCode } = this.props;
40-
if (
41-
code !== prevCode ||
42-
scope !== prevScope ||
43-
noInline !== prevNoInline ||
44-
transformCode !== prevTransformCode
45-
) {
46-
this.transpile({ code, scope, transformCode, noInline });
47-
}
48-
}
49-
50-
onChange = code => {
51-
const { scope, transformCode, noInline } = this.props;
52-
this.transpile({ code, scope, transformCode, noInline });
53-
};
54-
55-
onError = error => {
56-
this.setState({ error: error.toString() });
57-
};
58-
59-
transpile = ({ code, scope, transformCode, noInline = false }) => {
22+
function transpile(newCode) {
6023
// Transpilation arguments
6124
const input = {
62-
code: transformCode ? transformCode(code) : code,
25+
code: transformCode ? transformCode(newCode) : newCode,
6326
scope
6427
};
6528

66-
const errorCallback = err =>
67-
this.setState({ element: undefined, error: err.toString() });
68-
const renderElement = element => this.setState({ ...state, element });
29+
const errorCallback = error =>
30+
setState({ error: error.toString(), element: undefined });
6931

70-
// State reset object
71-
const state = { unsafeWrapperError: undefined, error: undefined };
32+
const renderElement = element => setState({ error: undefined, element });
7233

7334
try {
7435
if (noInline) {
75-
this.setState({ ...state, element: null }); // Reset output for async (no inline) evaluation
36+
setState({ error: undefined, element: null }); // Reset output for async (no inline) evaluation
7637
renderElementAsync(input, renderElement, errorCallback);
7738
} else {
7839
renderElement(generateElement(input, errorCallback));
7940
}
8041
} catch (error) {
81-
this.setState({ ...state, error: error.toString() });
42+
errorCallback(error);
8243
}
83-
};
44+
}
8445

85-
render() {
86-
const { children, code, language, theme, disabled } = this.props;
46+
useEffect(() => {
47+
transpile(code);
48+
}, [code, scope, noInline, transformCode]);
8749

88-
return (
89-
<LiveContext.Provider
90-
value={{
91-
...this.state,
92-
code,
93-
language,
94-
theme,
95-
disabled,
96-
onError: this.onError,
97-
onChange: this.onChange
98-
}}
99-
>
100-
{children}
101-
</LiveContext.Provider>
102-
);
103-
}
50+
const onChange = newCode => transpile(newCode);
51+
52+
const onError = error => setState({ error: error.toString() });
53+
54+
return (
55+
<LiveContext.Provider
56+
value={{
57+
...state,
58+
code,
59+
language,
60+
theme,
61+
disabled,
62+
onError,
63+
onChange
64+
}}
65+
>
66+
{children}
67+
</LiveContext.Provider>
68+
);
10469
}
70+
71+
LiveProvider.propTypes = {
72+
children: PropTypes.node,
73+
code: PropTypes.string,
74+
disabled: PropTypes.bool,
75+
language: PropTypes.string,
76+
noInline: PropTypes.bool,
77+
scope: PropTypes.object,
78+
theme: PropTypes.object,
79+
transformCode: PropTypes.func
80+
};
81+
82+
LiveProvider.defaultProps = {
83+
code: '',
84+
noInline: false,
85+
language: 'jsx',
86+
disabled: false
87+
};
88+
89+
export default LiveProvider;

stories/Live.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ function LikeButton() {
6262
6363
return (
6464
<>
65-
<p class="likes">{likes} likes</p>
65+
<p className="likes">{likes} likes</p>
6666
<button
67-
class="button"
67+
className="button"
6868
onClick={() => increaseLikes(likes + 1)} />
6969
</>
7070
)
@@ -139,7 +139,7 @@ const TestComponent = ({ live }) => {
139139
return (
140140
<Container>
141141
<StyledEditor />
142-
<Result />
142+
{Result && <Result />}
143143
<pre>{live.error}</pre>
144144
</Container>
145145
);

yarn.lock

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7875,15 +7875,15 @@ react-docgen@^3.0.0-beta11:
78757875
node-dir "^0.1.10"
78767876
recast "^0.16.0"
78777877

7878-
react-dom@^16.2.0:
7879-
version "16.9.0"
7880-
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962"
7881-
integrity sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ==
7878+
react-dom@^16.8.0:
7879+
version "16.13.1"
7880+
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
7881+
integrity sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==
78827882
dependencies:
78837883
loose-envify "^1.1.0"
78847884
object-assign "^4.1.1"
78857885
prop-types "^15.6.2"
7886-
scheduler "^0.15.0"
7886+
scheduler "^0.19.1"
78877887

78887888
react-error-overlay@^4.0.1:
78897889
version "4.0.1"
@@ -8013,10 +8013,10 @@ react-treebeard@^2.1.0:
80138013
shallowequal "^0.2.2"
80148014
velocity-react "^1.3.1"
80158015

8016-
react@^16.2.0:
8017-
version "16.9.0"
8018-
resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa"
8019-
integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==
8016+
react@^16.8.0:
8017+
version "16.13.1"
8018+
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
8019+
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
80208020
dependencies:
80218021
loose-envify "^1.1.0"
80228022
object-assign "^4.1.1"
@@ -8647,6 +8647,14 @@ scheduler@^0.15.0:
86478647
loose-envify "^1.1.0"
86488648
object-assign "^4.1.1"
86498649

8650+
scheduler@^0.19.1:
8651+
version "0.19.1"
8652+
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
8653+
integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
8654+
dependencies:
8655+
loose-envify "^1.1.0"
8656+
object-assign "^4.1.1"
8657+
86508658
schema-utils@^0.3.0:
86518659
version "0.3.0"
86528660
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"

0 commit comments

Comments
 (0)