Skip to content

Commit

Permalink
Update tests and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesrweb committed May 3, 2024
1 parent 23f573c commit 3190350
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 45 deletions.
111 changes: 110 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ Of course, you can also use any other css-in-js library or by just using simple
css to achieve almost anything you can imagine just by using the wrapper class
as your root selector.

## Fallback UIs
### Fallback UIs

Lets say you want to have a fallback UI in case the `sketch` ever falls out of
sync or is undefined for some reason. If this is a use case for you then you
Expand Down Expand Up @@ -515,6 +515,115 @@ In this case, by default the fallback UI containing
sketch, it will be rendered until you choose to once again "show nothing" which
falls back to the fallback UI.

### Error and Loading UIs

Since version 4.4.0, it was possible to add a `fallback` prop, see the section
on fallbacks.

Since version 5 it is now possible to pass an `error` and `loading` prop to the
wrapper which allow the user to pass different UIs for error and loading states.

- The `error` state will trigger if the sketch or the wrapper encounter an
issue, otherwise a default error view will be shown.
- The `loading` state will trigger while the wrapper is being lazy loaded,
otherwise a default loading view will be shown.

#### Error UIs

To show a custom UI when an error occurs within the sketch or the wrapper, you
can pass a lazy function to the `error` prop.

```tsx
import * as React from "react";
import { P5CanvasInstance, ReactP5Wrapper } from "@p5-wrapper/react";

// This child will throw an error, oh no!
function ErrorChild() {
throw new Error("oops");
}

// This view will catch the thrown error and give you access to what exactly was thrown.
function ErrorUI(error: any) {
if (error instanceof Error) {
return <p>An error occured: {error.message}</p>;
}

return <p>An unknown error occured: {error.toString()}</p>;
}

function sketch(p5: P5CanvasInstance) {
p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL);

p5.draw = () => {
p5.background(250);
p5.normalMaterial();
p5.push();
p5.rotateZ(p5.frameCount * 0.01);
p5.rotateX(p5.frameCount * 0.01);
p5.rotateY(p5.frameCount * 0.01);
p5.plane(100);
p5.pop();
};
}

export function App() {
return (
<ReactP5Wrapper sketch={sketch} error={ErrorUI}>
<ErrorChild />
</ReactP5Wrapper>
);
}
```

Instead of the sketch, this will render `<p>An error occured: oops</p>`. Note
that in truth, the `ErrorView` will **always** receive `any` values since JS /
TS allow you to `throw` whatever values you want to, this is why we have to add
the `error instanceof Error` check to be sure the value we got was actually an
`Error` instance and not some other value like a `number`, `string`, `object` or
anything else that could be thrown by JS / TS.

As mentioned above, the `error` state will trigger if the sketch or the wrapper
encounter an issue, otherwise a default error view will be shown.

#### Loading UIs

To show a custom UI while the sketch UI is being lazy loaded, you can pass a
lazy function to the `loading` prop.

```tsx
import * as React from "react";
import { P5CanvasInstance, ReactP5Wrapper } from "@p5-wrapper/react";

function LoadingUI() {
return <p>The sketch is being loaded.</p>;
}

function sketch(p5: P5CanvasInstance) {
p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL);

p5.draw = () => {
p5.background(250);
p5.normalMaterial();
p5.push();
p5.rotateZ(p5.frameCount * 0.01);
p5.rotateX(p5.frameCount * 0.01);
p5.rotateY(p5.frameCount * 0.01);
p5.plane(100);
p5.pop();
};
}

export function App() {
return <ReactP5Wrapper sketch={sketch} loading={LoadingUI} />;
}
```

In the initial period between the sketch render starting and it's lazy loading
ending, the `LoadingUI` will be shown!

As mentioned above, the `loading` state will trigger while the wrapper is being
lazy loaded, otherwise a default loading view will be shown.

## P5 plugins and constructors

As discussed in multiple issues such as
Expand Down
16 changes: 16 additions & 0 deletions config/eslint/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import eslint from "@eslint/js";
import { dirname } from "path";
import tseslint from "typescript-eslint";

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
languageOptions: {
parserOptions: {
project: true,
tsconfigRootDir: dirname(dirname(import.meta.dirname))
}
}
}
);
26 changes: 0 additions & 26 deletions config/eslint/eslint.json

This file was deleted.

5 changes: 3 additions & 2 deletions config/typescript/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false,
"jsx": "react-jsx"
"jsx": "react-jsx",
"noImplicitAny": true
},
"include": ["../../src", "../../tests"],
"include": ["../../src", "../../tests", "../../config"],
"references": [{ "path": "./tsconfig.node.json" }]
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"dev": "vite --config config/vite/vite.demo.config.ts --host",
"format": "pnpm prettier --write .",
"format:check": "pnpm prettier --check .",
"lint": "eslint --ignore-pattern .gitignore --config config/eslint/eslint.json .",
"lint": "eslint --ignore-pattern .gitignore --config config/eslint/eslint.config.js .",
"lint:fix": "pnpm lint --fix",
"prettier": "prettier --config config/prettier/prettier.json --ignore-path .gitignore",
"test": "vitest run --config config/vite/vite.component.config.ts",
Expand Down Expand Up @@ -88,7 +88,7 @@
"react-dom": ">= 18.2.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.4.3",
"@testing-library/jest-dom": "6.4.2",
"@testing-library/react": "^15.0.6",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/jest": "^29.5.12",
Expand All @@ -107,6 +107,7 @@
"prettier": "^3.2.5",
"rimraf": "^5.0.5",
"typescript": "^5.4.5",
"typescript-eslint": "^7.8.0",
"vite": "^5.2.11",
"vitest": "^1.5.3",
"vitest-canvas-mock": "^0.3.3"
Expand Down
42 changes: 37 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion src/components/ReactP5WrapperGuard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { logErrorBoundaryError } from "../utils/logErrorBoundaryError";
const ReactP5WrapperWithSketch = React.lazy(
() => import("./ReactP5WrapperWithSketch")
);

const ErrorBoundary = React.lazy(() =>
import("react-error-boundary").then(m => ({
default: m.ErrorBoundary
Expand All @@ -34,7 +35,11 @@ export default function ReactP5WrapperGuard<
}}
onError={logErrorBoundaryError}
>
<React.Suspense fallback={props.loading?.() ?? <p>🚀 Loading...</p>}>
<React.Suspense
fallback={
props.loading?.() ?? <p data-testid="loading">🚀 Loading...</p>
}
>
<ReactP5WrapperWithSketch
/** @see https://github.com/P5-wrapper/react/issues/207 */
{...(props as unknown as P5WrapperPropsWithSketch<Props>)}
Expand Down
Loading

0 comments on commit 3190350

Please sign in to comment.