Skip to content

Commit

Permalink
Move LiveProvider to a functional component with hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
bkonkle committed Oct 2, 2020
1 parent 2cf946e commit a65992e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/components/Editor/index.js
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
146 changes: 65 additions & 81 deletions src/components/Live/LiveProvider.js
@@ -1,105 +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
};

state = { unsafeWrapperError: undefined, error: undefined, element: React.Fragment }

componentDidMount() {
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
};

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

const errorCallback = err =>
this.setState({ element: undefined, error: err.toString() });
const renderElement = element => this.setState({ ...state, element });
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
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

0 comments on commit a65992e

Please sign in to comment.