Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move LiveProvider to hooks, fixes #220 #226

Merged
merged 6 commits into from
Jun 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions demo/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const path = require('path');
module.exports = {
webpack: config => {
config.resolve.alias['react-live'] = path.resolve('../');
config.resolve.alias.react = path.resolve('./node_modules/react');
config.resolve.alias['react-dom'] = path.resolve('./node_modules/react-dom');

return config;
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
"eslint-plugin-react": "^7.7.0",
"jest": "^22.2.1",
"prettier": "^1.17.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"rollup": "^0.55.3",
"rollup-plugin-babel": "^3.0.3",
"rollup-plugin-commonjs": "^8.3.0",
Expand Down
12 changes: 2 additions & 10 deletions src/components/Editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { theme as liveTheme } from '../../constants/theme';
class CodeEditor extends Component {
static propTypes = {
code: PropTypes.string,
disabled: PropTypes.boolean,
disabled: PropTypes.bool,
language: PropTypes.string,
onChange: PropTypes.func,
style: PropTypes.object,
Expand Down Expand Up @@ -58,15 +58,7 @@ class CodeEditor extends Component {
);

render() {
// eslint-disable-next-line no-unused-vars
const {
style,
code: _code,
onChange,
language,
theme,
...rest
} = this.props;
const { style, theme, ...rest } = this.props;
const { code } = this.state;

const baseTheme =
Expand Down
5 changes: 5 additions & 0 deletions src/components/Live/LivePreview.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import LiveContext from './LiveContext';

function LivePreview({ Component, ...rest }) {
Expand All @@ -11,6 +12,10 @@ function LivePreview({ Component, ...rest }) {
);
}

LivePreview.propTypes = {
Component: PropTypes.node
};

LivePreview.defaultProps = {
Component: 'div'
};
Expand Down
145 changes: 65 additions & 80 deletions src/components/Live/LiveProvider.js
Original file line number Diff line number Diff line change
@@ -1,104 +1,89 @@
import React, { Component } from 'react';
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';

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

export default class LiveProvider extends Component {
static defaultProps = {
code: '',
noInline: false,
language: 'jsx',
disabled: false
};
function LiveProvider({
children,
code,
language,
theme,
disabled,
scope,
transformCode,
noInline = false
}) {
const [state, setState] = useState({
error: undefined,
element: undefined
});

static propTypes = {
children: PropTypes.children,
code: PropTypes.string,
disabled: PropTypes.bool,
language: PropTypes.string,
noInline: PropTypes.bool,
scope: PropTypes.object,
theme: PropTypes.object,
transformCode: PropTypes.node
};

// eslint-disable-next-line camelcase
UNSAFE_componentWillMount() {
const { code, scope, transformCode, noInline } = this.props;

this.transpile({ code, scope, transformCode, noInline });
}

componentDidUpdate({
code: prevCode,
scope: prevScope,
noInline: prevNoInline,
transformCode: prevTransformCode
}) {
const { code, scope, noInline, transformCode } = this.props;
if (
code !== prevCode ||
scope !== prevScope ||
noInline !== prevNoInline ||
transformCode !== prevTransformCode
) {
this.transpile({ code, scope, transformCode, noInline });
}
}

onChange = code => {
const { scope, transformCode, noInline } = this.props;
this.transpile({ code, scope, transformCode, noInline });
};

onError = error => {
this.setState({ error: error.toString() });
};

transpile = ({ code, scope, transformCode, noInline = false }) => {
function transpile(newCode) {
// Transpilation arguments
const input = {
code: transformCode ? transformCode(code) : code,
code: transformCode ? transformCode(newCode) : newCode,
scope
};

const errorCallback = err =>
this.setState({ element: undefined, error: err.toString() });
const renderElement = element => this.setState({ ...state, element });
const errorCallback = error =>
setState({ error: error.toString(), element: undefined });

// State reset object
const state = { unsafeWrapperError: undefined, error: undefined };
const renderElement = element => setState({ error: undefined, element });

try {
if (noInline) {
this.setState({ ...state, element: null }); // Reset output for async (no inline) evaluation
setState({ error: undefined, element: null }); // Reset output for async (no inline) evaluation
renderElementAsync(input, renderElement, errorCallback);
} else {
renderElement(generateElement(input, errorCallback));
}
} catch (error) {
this.setState({ ...state, error: error.toString() });
errorCallback(error);
}
};
}

render() {
const { children, code, language, theme, disabled } = this.props;
useEffect(() => {
transpile(code);
}, [code, scope, noInline, transformCode]);

return (
<LiveContext.Provider
value={{
...this.state,
code,
language,
theme,
disabled,
onError: this.onError,
onChange: this.onChange
}}
>
{children}
</LiveContext.Provider>
);
}
const onChange = newCode => transpile(newCode);

const onError = error => setState({ error: error.toString() });

return (
<LiveContext.Provider
value={{
...state,
code,
language,
theme,
disabled,
onError,
onChange
}}
>
{children}
</LiveContext.Provider>
);
}

LiveProvider.propTypes = {
children: PropTypes.node,
code: PropTypes.string,
disabled: PropTypes.bool,
language: PropTypes.string,
noInline: PropTypes.bool,
scope: PropTypes.object,
theme: PropTypes.object,
transformCode: PropTypes.func
};

LiveProvider.defaultProps = {
code: '',
noInline: false,
language: 'jsx',
disabled: false
};

export default LiveProvider;
6 changes: 3 additions & 3 deletions stories/Live.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ function LikeButton() {

return (
<>
<p class="likes">{likes} likes</p>
<p className="likes">{likes} likes</p>
<button
class="button"
className="button"
onClick={() => increaseLikes(likes + 1)} />
</>
)
Expand Down Expand Up @@ -139,7 +139,7 @@ const TestComponent = ({ live }) => {
return (
<Container>
<StyledEditor />
<Result />
{Result && <Result />}
<pre>{live.error}</pre>
</Container>
);
Expand Down
26 changes: 17 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7883,15 +7883,15 @@ react-docgen@^3.0.0-beta11:
node-dir "^0.1.10"
recast "^0.16.0"

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

react-error-overlay@^4.0.1:
version "4.0.1"
Expand Down Expand Up @@ -8021,10 +8021,10 @@ react-treebeard@^2.1.0:
shallowequal "^0.2.2"
velocity-react "^1.3.1"

react@^16.2.0:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa"
integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==
react@^16.8.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"
integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
Expand Down Expand Up @@ -8655,6 +8655,14 @@ scheduler@^0.15.0:
loose-envify "^1.1.0"
object-assign "^4.1.1"

scheduler@^0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"

schema-utils@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
Expand Down