React Runner
React Runner is a JavaScript library designed for executing and previewing live React code directly within a web application. Currently stable at version 1.0.5, it provides components and hooks to dynamically run arbitrary React code snippets, supporting modern JavaScript features like class fields, arrow functions for event handlers, and `import` statements. Unlike alternatives like `react-live` which use Bublé, React Runner leverages Sucrase for transpilation, offering broader compatibility with contemporary syntax and TypeScript without enforcing strict coding patterns. It facilitates scenarios such as interactive documentation, code playgrounds, and component development environments, offering features like multi-file code execution and server-side rendering support. While there isn't an explicit release cadence mentioned, the 1.x.x versioning implies ongoing maintenance within this major branch.
Common errors
-
ReferenceError: [variable] is not defined
cause A variable, component, or module used within the live `code` string is not provided in the `scope` prop.fixEnsure all external variables, components (e.g., `React`, `useState`), or modules that the `code` string relies on are explicitly passed within the `scope` object. -
SyntaxError: Unexpected token 'import'
cause Attempting to use `import` statements in the live code without correctly configuring the `import` property in the `scope` prop, or incorrect module path resolution.fixDefine the `import` object within your `scope` prop, mapping module names to their corresponding values. Use `importCode(localFileContent, baseScope)` for local file imports. -
React is not defined
cause The React library itself or `React` global object is not available in the `scope` provided to `react-runner`.fixAdd `React` (and potentially `ReactDOM` or `useState`, `useEffect` if used as direct imports) to your `scope` prop: `scope={{ React, useState }}`.
Warnings
- gotcha Browser support is restricted to modern evergreen browsers (Chrome > 61, Edge > 16, Firefox > 60, Safari > 10.1). Older browsers or specific environments might require polyfills or fail to run the transpiled code.
- gotcha While `react-runner` uses Sucrase for modern JS/TS features, it still performs a transpilation step on the provided code. Complex build-time transformations, specific Babel plugins, or highly experimental syntax might not be supported within the live code environment.
- gotcha Migrating from `react-live` to `react-runner` might require adapting your component structure or scope definition, as `react-runner` provides a different API for component and hook usage. While `react-live-runner` exists as an adapter, direct migration needs careful review.
Install
-
npm install react-runner -
yarn add react-runner -
pnpm add react-runner
Imports
- Runner
const { Runner } = require('react-runner')import { Runner } from 'react-runner' - useRunner
const { useRunner } = require('react-runner')import { useRunner } from 'react-runner' - importCode
const { importCode } = require('react-runner')import { importCode } from 'react-runner'
Quickstart
import React, { useState } from 'react';
import { Runner } from 'react-runner';
const initialCode = `
import { Button } from './MyComponents';
function MyLiveComponent() {
const [count, setCount] = React.useState(0);
return (
<div style={{ padding: 20, border: '1px solid #eee' }}>
<h2>Live Counter: {count}</h2>
<Button onClick={() => setCount(c => c + 1)}>Increment</Button>
</div>
);
}
export default MyLiveComponent;
`;
const MyButton = ({ children, onClick }) => (
<button style={{ background: 'blue', color: 'white', padding: '10px 15px', borderRadius: '5px', border: 'none', cursor: 'pointer' }} onClick={onClick}>
{children}
</button>
);
const App = () => {
const [code, setCode] = useState(initialCode);
const scope = {
React,
useState,
Button: MyButton,
import: {
'./MyComponents': { Button: MyButton }
}
};
const handleRendered = () => console.log('Live component rendered!');
return (
<div>
<h3>Edit the code below:</h3>
<textarea
value={code}
onChange={(e) => setCode(e.target.value)}
rows={15}
cols={80}
style={{ width: '100%', minHeight: '200px', marginBottom: '20px', fontFamily: 'monospace' }}
/>
<h3>Live Preview:</h3>
<Runner code={code} scope={scope} onRendered={handleRendered} />
</div>
);
};
export default App;