UNPKG

react-toolbox

Version:
101 lines (84 loc) 2.28 kB
import React from 'react'; import ReactDOM from 'react-dom'; import babel from 'babel-core/browser'; import ReactToolbox from 'react-toolbox'; import style from './style'; const ERROR_TIMEOUT = 500; const Preview = React.createClass({ propTypes: { className: React.PropTypes.string, code: React.PropTypes.string.isRequired, scope: React.PropTypes.object }, getDefaultProps () { return { className: '', scope: Object.assign({ React }, ReactToolbox) }; }, getInitialState () { return { error: null }; }, componentDidMount () { this.executeCode(); }, componentDidUpdate (prevProps) { clearTimeout(this.timeoutID); if (this.props.code !== prevProps.code) { this.executeCode(); } }, setTimeout () { clearTimeout(this.timeoutID); this.timeoutID = setTimeout.apply(null, arguments); }, compileCode () { const code = ` (function (${Object.keys(this.props.scope).join(', ')}, mountNode) { ${this.props.code} });`; return babel.transform(code, { optional: ['es7.classProperties'] }).code; }, buildScope (mountNode) { return Object.keys(this.props.scope).map((key) => { return this.props.scope[key]; }).concat(mountNode); }, executeCode () { const mountNode = this.refs.mount; const scope = this.buildScope(mountNode); try { ReactDOM.unmountComponentAtNode(mountNode); } catch (e) { console.error(e); } try { const compiledCode = this.compileCode(); /*eslint-disable no-eval*/ const Component = eval(compiledCode).apply(null, scope); ReactDOM.render(Component, mountNode); if (this.state.error) { this.setState({error: null}); } } catch (err) { this.setTimeout(() => { this.setState({error: err.toString()}); }, ERROR_TIMEOUT); } }, render () { let className = style.preview; if (this.props.className) className += ` ${this.props.className}`; return ( <div className={className}> {this.state.error !== null ? <span className={style.error}>{this.state.error}</span> : null} <div ref="mount" className={style.content} /> </div> ); } }); export default Preview;