Skip to content

Commit

Permalink
feat: add createRequire and remove imports
Browse files Browse the repository at this point in the history
  • Loading branch information
nihgwu committed Jan 11, 2022
1 parent cf98e42 commit 885d984
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 82 deletions.
48 changes: 33 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Run your React code on the go [https://react-runner.vercel.app](https://react-ru
- Function component
- Class component, **with class fields support**
- Composing components with `render` or `export default`
- Support `Typescript`
- Server Side Rendering
- Support `Typescript`
- Support `import` statement via `createRequire` utility

Hacker News [in react-runner](https://react-runner.vercel.app/#hacker-news) vs [in real world](https://react-runner.vercel.app/examples/hacker-news), with the same code

Expand All @@ -27,31 +28,49 @@ npm install --save react-runner

- **code** `string`, _required_ the code to be ran
- **scope** `object` globals that could be used in `code`
- **imports** `object` imports that could be used in `code`

### Predefined scope

```js
{
React,
jsxPragma: React.createElement, // useful if you are using Emotion with `css` prop
jsxFragmentPragma: React.Fragment,
}
```

## Usage

```jsx
import { useRunner } from 'react-runner'

const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })
```

or use `Runner` as a component directly and handle error with `onRendered`

```jsx
import { Runner } from 'react-runner'

const element = (
<Runner
code={code}
scope={scope}
imports={imports}
onRendered={handleRendered}
/>
)
const element = <Runner code={code} scope={scope} onRendered={handleRendered} />
```

### `import` statement

```js
// you can define your own version of `createRequire`
import { createRequire } from 'react-runner'
import * as YourPkg from 'your-pkg'

const scope = {
require: createRquire({
'your-pkg': YourPkg,
}),
}
```

then in your code you can use `import Foo, { Bar } from 'your-pkg'`

## Browser support

```
Expand All @@ -70,7 +89,7 @@ I love it, but I love arrow functions for event handlers instead of bind them ma
and I don't want to change my code to be compliant with restrictions, so I created this project,
use [Sucrase](https://github.com/alangpierce/sucrase) instead of [Bublé](https://github.com/bublejs/buble) to transpile the code.

If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with:
If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with, and `react-live-runner` re-exports `react-runner` so you can use everything in `react-runner` by importing `react-live-runner`

```jsx
import {
Expand All @@ -81,7 +100,7 @@ import {
} from 'react-live-runner'

...
<LiveProvider code={code} scope={scope} imports={imports}>
<LiveProvider code={code} scope={scope}>
<LiveEditor />
<LivePreview />
<LiveError />
Expand All @@ -97,7 +116,6 @@ import { useLiveRunner, CodeEditor } from 'react-live-runner'
const { element, error, code, onChange } = useLiveRunner({
initialCode,
scope,
imports,
transformCode,
})

Expand All @@ -117,7 +135,7 @@ import { useState, useEffect } from 'react'
import { useRunner } from 'react-runner'

const [code, onChange] = useState(initialCode)
const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })

useEffect(() => {
onChange(initialCode)
Expand Down
48 changes: 33 additions & 15 deletions packages/react-live-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Run your React code on the go [https://react-runner.vercel.app](https://react-ru
- Function component
- Class component, **with class fields support**
- Composing components with `render` or `export default`
- Support `Typescript`
- Server Side Rendering
- Support `Typescript`
- Support `import` statement via `createRequire` utility

Hacker News [in react-runner](https://react-runner.vercel.app/#hacker-news) vs [in real world](https://react-runner.vercel.app/examples/hacker-news), with the same code

Expand All @@ -27,31 +28,49 @@ npm install --save react-runner

- **code** `string`, _required_ the code to be ran
- **scope** `object` globals that could be used in `code`
- **imports** `object` imports that could be used in `code`

### Predefined scope

```js
{
React,
jsxPragma: React.createElement, // useful if you are using Emotion with `css` prop
jsxFragmentPragma: React.Fragment,
}
```

## Usage

```jsx
import { useRunner } from 'react-runner'

const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })
```

or use `Runner` as a component directly and handle error with `onRendered`

```jsx
import { Runner } from 'react-runner'

const element = (
<Runner
code={code}
scope={scope}
imports={imports}
onRendered={handleRendered}
/>
)
const element = <Runner code={code} scope={scope} onRendered={handleRendered} />
```

### `import` statement

```js
// you can define your own version of `createRequire`
import { createRequire } from 'react-runner'
import * as YourPkg from 'your-pkg'

const scope = {
require: createRquire({
'your-pkg': YourPkg,
}),
}
```

then in your code you can use `import Foo, { Bar } from 'your-pkg'`

## Browser support

```
Expand All @@ -70,7 +89,7 @@ I love it, but I love arrow functions for event handlers instead of bind them ma
and I don't want to change my code to be compliant with restrictions, so I created this project,
use [Sucrase](https://github.com/alangpierce/sucrase) instead of [Bublé](https://github.com/bublejs/buble) to transpile the code.

If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with:
If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with, and `react-live-runner` re-exports `react-runner` so you can use everything in `react-runner` by importing `react-live-runner`

```jsx
import {
Expand All @@ -81,7 +100,7 @@ import {
} from 'react-live-runner'

...
<LiveProvider code={code} scope={scope} imports={imports}>
<LiveProvider code={code} scope={scope}>
<LiveEditor />
<LivePreview />
<LiveError />
Expand All @@ -97,7 +116,6 @@ import { useLiveRunner, CodeEditor } from 'react-live-runner'
const { element, error, code, onChange } = useLiveRunner({
initialCode,
scope,
imports,
transformCode,
})

Expand All @@ -117,7 +135,7 @@ import { useState, useEffect } from 'react'
import { useRunner } from 'react-runner'

const [code, onChange] = useState(initialCode)
const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })

useEffect(() => {
onChange(initialCode)
Expand Down
48 changes: 33 additions & 15 deletions packages/react-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Run your React code on the go [https://react-runner.vercel.app](https://react-ru
- Function component
- Class component, **with class fields support**
- Composing components with `render` or `export default`
- Support `Typescript`
- Server Side Rendering
- Support `Typescript`
- Support `import` statement via `createRequire` utility

Hacker News [in react-runner](https://react-runner.vercel.app/#hacker-news) vs [in real world](https://react-runner.vercel.app/examples/hacker-news), with the same code

Expand All @@ -27,31 +28,49 @@ npm install --save react-runner

- **code** `string`, _required_ the code to be ran
- **scope** `object` globals that could be used in `code`
- **imports** `object` imports that could be used in `code`

### Predefined scope

```js
{
React,
jsxPragma: React.createElement, // useful if you are using Emotion with `css` prop
jsxFragmentPragma: React.Fragment,
}
```

## Usage

```jsx
import { useRunner } from 'react-runner'

const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })
```

or use `Runner` as a component directly and handle error with `onRendered`

```jsx
import { Runner } from 'react-runner'

const element = (
<Runner
code={code}
scope={scope}
imports={imports}
onRendered={handleRendered}
/>
)
const element = <Runner code={code} scope={scope} onRendered={handleRendered} />
```

### `import` statement

```js
// you can define your own version of `createRequire`
import { createRequire } from 'react-runner'
import * as YourPkg from 'your-pkg'

const scope = {
require: createRquire({
'your-pkg': YourPkg,
}),
}
```

then in your code you can use `import Foo, { Bar } from 'your-pkg'`

## Browser support

```
Expand All @@ -70,7 +89,7 @@ I love it, but I love arrow functions for event handlers instead of bind them ma
and I don't want to change my code to be compliant with restrictions, so I created this project,
use [Sucrase](https://github.com/alangpierce/sucrase) instead of [Bublé](https://github.com/bublejs/buble) to transpile the code.

If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with:
If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with, and `react-live-runner` re-exports `react-runner` so you can use everything in `react-runner` by importing `react-live-runner`

```jsx
import {
Expand All @@ -81,7 +100,7 @@ import {
} from 'react-live-runner'

...
<LiveProvider code={code} scope={scope} imports={imports}>
<LiveProvider code={code} scope={scope}>
<LiveEditor />
<LivePreview />
<LiveError />
Expand All @@ -97,7 +116,6 @@ import { useLiveRunner, CodeEditor } from 'react-live-runner'
const { element, error, code, onChange } = useLiveRunner({
initialCode,
scope,
imports,
transformCode,
})

Expand All @@ -117,7 +135,7 @@ import { useState, useEffect } from 'react'
import { useRunner } from 'react-runner'

const [code, onChange] = useState(initialCode)
const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })

useEffect(() => {
onChange(initialCode)
Expand Down
6 changes: 3 additions & 3 deletions packages/react-runner/src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { create } from 'react-test-renderer'

import { generateElement } from '../utils'
import { generateElement, createRequire } from '../utils'

test('empty code', () => {
const element = generateElement({ code: `` })
Expand Down Expand Up @@ -227,7 +227,7 @@ test('imports', () => {
const element = generateElement({
code: `import Foo from 'foo'
render(<Foo />)`,
imports: { foo: () => 'hello' },
scope: { require: createRequire({ foo: () => 'hello' }) },
})

expect(element).toMatchInlineSnapshot(`<foo />`)
Expand All @@ -239,7 +239,7 @@ test('invalid imports', () => {
generateElement({
code: `import Foo from 'foo'
render(<Foo />)`,
imports: { bar: () => 'hello' },
scope: { require: createRequire({ bar: () => 'hello' }) },
})
).toThrowErrorMatchingInlineSnapshot(`"Module not found: 'foo'"`)
})
4 changes: 2 additions & 2 deletions packages/react-runner/src/transform.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { transform as _transform } from 'sucrase'

export const transform = (code: string, hasImports?: boolean) => {
export const transform = (code: string, transformImports?: boolean) => {
return _transform(code, {
transforms: hasImports
transforms: transformImports
? ['jsx', 'typescript', 'imports']
: ['jsx', 'typescript'],
production: true,
Expand Down
2 changes: 0 additions & 2 deletions packages/react-runner/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@ export type RunnerOptions = {
code: string
/** globals that could be used in code */
scope?: Scope
/** imports that could be used in code */
imports?: Scope
}
5 changes: 0 additions & 5 deletions packages/react-runner/src/useRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,17 @@ export type UseRunnerReturn = {
export const useRunner = ({
code,
scope,
imports,
disableCache,
}: UseRunnerProps): UseRunnerReturn => {
const isMountRef = useRef(true)
const elementRef = useRef<ReactElement | null>(null)
const scopeRef = useRef(scope)
scopeRef.current = scope
const importsRef = useRef(imports)
importsRef.current = imports

const [state, setState] = useState<UseRunnerReturn>(() => {
const element = createElement(Runner, {
code,
scope: scopeRef.current,
imports: importsRef.current,
onRendered: (error) => {
if (error) {
setState({
Expand All @@ -54,7 +50,6 @@ export const useRunner = ({
const element = createElement(Runner, {
code,
scope: scopeRef.current,
imports: importsRef.current,
onRendered: (error) => {
if (error) {
setState({
Expand Down
Loading

0 comments on commit 885d984

Please sign in to comment.