Skip to content

Commit

Permalink
fix: wrap preview in boundary (#392)
Browse files Browse the repository at this point in the history
Co-authored-by: Charles Brown <[email protected]>
  • Loading branch information
r281GQ and carbonrobot authored Nov 19, 2024
1 parent 7d7ef30 commit 20050af
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/silent-ads-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-live": patch
---

Wrap preview in error boundary
10 changes: 5 additions & 5 deletions .github/workflows/code-check.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
name: Code Check

on:
push:
branches:
- master
pull_request:
branches:
- master
Expand All @@ -16,8 +13,11 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup

- name: Check Code ${{ matrix.node-version }}
- name: Check Code
run: pnpm lint

- name: Build ${{ matrix.node-version }}
- name: Test
run: pnpm test

- name: Build
run: pnpm build
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: react-live Release Workflow
name: Release Workflow

on:
push:
Expand All @@ -21,6 +21,12 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup

- name: Check Code
run: pnpm lint

- name: Test
run: pnpm test

- name: Build packages
run: pnpm run build

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"build:lib": "pnpm run --filter react-live build",
"lint": "pnpm run --parallel lint",
"lint:fix": "pnpm run --parallel lint --fix",
"test": "pnpm run --filter react-live test",
"changeset": "changeset",
"version": "pnpm changeset version && pnpm install --no-frozen-lockfile"
},
Expand Down
33 changes: 33 additions & 0 deletions packages/react-live/src/components/Live/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Component, ReactNode } from "react";

type Props = {
children: ReactNode;
onError?: (error: Error) => void;
};

type State = {
hasError: boolean;
};

export class ErrorBoundary extends Component<Props, State> {
static getDerivedStateFromError() {
return { hasError: true };
}

constructor(props: Props) {
super(props);
this.state = { hasError: false };
}

componentDidCatch(err: Error): void {
this.props.onError?.(err);
}

render() {
if (this.state.hasError) {
return null;
}

return this.props.children;
}
}
1 change: 1 addition & 0 deletions packages/react-live/src/components/Live/LiveContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ type ContextValue = {
error?: string;
element?: ComponentType | null;
code: string;
newCode?: string;
disabled: boolean;
language: string;
theme?: typeof themes.nightOwl;
Expand Down
11 changes: 9 additions & 2 deletions packages/react-live/src/components/Live/LivePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React, { useContext } from "react";

import { ErrorBoundary } from "./ErrorBoundary";
import LiveContext from "./LiveContext";

type Props<T extends React.ElementType = React.ElementType> = {
Expand All @@ -11,7 +13,12 @@ function LivePreview<T extends keyof JSX.IntrinsicElements>(
function LivePreview<T extends React.ElementType>(props: Props<T>): JSX.Element;

function LivePreview({ Component = "div", ...rest }: Props): JSX.Element {
const { element: Element } = useContext(LiveContext);
return <Component {...rest}>{Element ? <Element /> : null}</Component>;
const { element: Element, onError, newCode } = useContext(LiveContext);

return (
<ErrorBoundary key={newCode} onError={onError}>
<Component {...rest}>{Element ? <Element /> : null}</Component>
</ErrorBoundary>
);
}
export default LivePreview;
15 changes: 12 additions & 3 deletions packages/react-live/src/components/Live/LiveProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { themes } from "prism-react-renderer";
type ProviderState = {
element?: ComponentType | null;
error?: string;
newCode?: string;
};

type Props = {
Expand Down Expand Up @@ -37,7 +38,11 @@ function LiveProvider({

async function transpileAsync(newCode: string) {
const errorCallback = (error: Error) => {
setState({ error: error.toString(), element: undefined });
setState((previousState) => ({
...previousState,
error: error.toString(),
element: undefined,
}));
};

// - transformCode may be synchronous or asynchronous.
Expand All @@ -51,7 +56,7 @@ function LiveProvider({
try {
const transformedCode = await Promise.resolve(transformResult);
const renderElement = (element: ComponentType) =>
setState({ error: undefined, element });
setState({ error: undefined, element, newCode });

if (typeof transformedCode !== "string") {
throw new Error("Code failed to transform");
Expand All @@ -65,7 +70,11 @@ function LiveProvider({
};

if (noInline) {
setState({ error: undefined, element: null }); // Reset output for async (no inline) evaluation
setState((previousState) => ({
...previousState,
error: undefined,
element: null,
})); // Reset output for async (no inline) evaluation
renderElementAsync(input, renderElement, errorCallback);
} else {
renderElement(generateElement(input, errorCallback));
Expand Down
2 changes: 1 addition & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"lint": "eslint --ext .js,.ts,.tsx src",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"serve": "docusaurus serve --config ./docusaurus.config.js --dir ./build/open-source/react-live --port 3565 --no-open",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
Expand Down

0 comments on commit 20050af

Please sign in to comment.