{"id":23640687,"url":"https://github.com/p5-wrapper/react","last_synced_at":"2025-05-14T16:12:22.232Z","repository":{"id":37003596,"uuid":"77069393","full_name":"P5-wrapper/react","owner":"P5-wrapper","description":"A wrapper component that allows you to utilise P5 sketches within React apps.","archived":false,"fork":false,"pushed_at":"2025-04-04T17:50:34.000Z","size":10966,"stargazers_count":526,"open_issues_count":1,"forks_count":50,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-10T14:19:40.932Z","etag":null,"topics":["animation","component","creative-coding","graphics-programming","javascript","p5","react","sketches","typescript"],"latest_commit_sha":null,"homepage":"https://P5-wrapper.github.io/react/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/P5-wrapper.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":".github/SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-21T16:45:58.000Z","updated_at":"2025-04-09T16:23:40.000Z","dependencies_parsed_at":"2023-10-12T21:31:54.174Z","dependency_job_id":"ce59f539-856d-4fef-8554-3d2ba7d51987","html_url":"https://github.com/P5-wrapper/react","commit_stats":{"total_commits":343,"total_committers":12,"mean_commits":"28.583333333333332","dds":0.5830903790087463,"last_synced_commit":"438bd7ac1d3a4d3b8193ac9aa7d7edf7c0b16c1c"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P5-wrapper%2Freact","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P5-wrapper%2Freact/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P5-wrapper%2Freact/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/P5-wrapper%2Freact/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/P5-wrapper","download_url":"https://codeload.github.com/P5-wrapper/react/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248695319,"owners_count":21146952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","component","creative-coding","graphics-programming","javascript","p5","react","sketches","typescript"],"created_at":"2024-12-28T09:50:22.624Z","updated_at":"2025-04-13T09:57:23.015Z","avatar_url":"https://github.com/P5-wrapper.png","language":"TypeScript","readme":"![@P5-wrapper/react](https://socialify.git.ci/p5-wrapper/react/image?description=1\u0026font=Rokkitt\u0026forks=1\u0026issues=1\u0026language=1\u0026logo=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2Fc%2Fc6%2FP5.js_icon.svg%2F1920px-P5.js_icon.svg.png%3F20210812123459\u0026name=1\u0026owner=1\u0026pattern=Floating%20Cogs\u0026pulls=1\u0026stargazers=1\u0026theme=Auto)\n\n# @P5-wrapper/react\n\nA component to integrate [P5.js](https://p5js.org/) sketches into\n[React](https://reactjs.org/) apps.\n\n\u003e Note: Version 5 is still in development, currently 5.0.0-rc.0 has been\n\u003e released for internal development testing ONLY. It is recommended to continue\n\u003e utilising version 4.4.0 until it is out of the `rc` versioning scheme.\n\n## Installation\n\nTo install, use the following command in the format appropriate to your chosen\npackage manager:\n\n```shell\n[npm|yarn|pnpm] [install|add] p5 @p5-wrapper/react\n```\n\n### Peer dependencies\n\nPlease note that `p5`, `react` and `react-dom` are peer dependencies, meaning\nyou should ensure they are installed before installing React P5 Wrapper.\n\n```js\n\"peerDependencies\": {\n  \"p5\": \"\u003e= 1.4.1\",\n  \"react\": \"\u003e= 18.2.0\",\n  \"react-dom\": \"\u003e= 18.2.0\"\n},\n```\n\n### TypeScript\n\nIf you would like to use Typescript, you should install `p5` types in the\ndevelopment environment:\n\n```shell\n[npm|yarn|pnpm] [install|add] -D @types/p5\n```\n\n### Next.js\n\nIf you plan to use this component within a Next.js application, you should\ninstead use\n[our Next.js dynamic implementation](https://github.com/P5-wrapper/next)\ninstead. To do get started, you can run:\n\n```shell\n[npm|yarn|pnpm] [install|add] p5 @p5-wrapper/next @p5-wrapper/react\n```\n\nPlease continue reading these docs and also look at\n[the Next.js dynamic implementation docs](https://github.com/P5-wrapper/next)\nfor further supporting information.\n\n## Demo \u0026 Examples\n\n### Live demo\n\nA live demo can be viewed at\n[P5-wrapper.github.io/react](https://P5-wrapper.github.io/react/).\n\n### Examples\n\nThe repository contains further\n[examples](https://github.com/P5-wrapper/react/tree/master/demo/sketches).\n\nTo try them out for yourself fork the repository, be sure you have\n[PNPM](https://pnpm.io/) installed and then run the following:\n\n```sh\ngit clone git@github.com:\u003cyour username\u003e/react.git\ncd react\npnpm install\npnpm preview\n```\n\nThen just open `http://localhost:3001` in a browser.\n\n## Usage\n\n### Javascript\n\n```jsx\nimport * as React from \"react\";\nimport { ReactP5Wrapper } from \"@p5-wrapper/react\";\n\nfunction sketch(p5) {\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.draw = () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n}\n\nexport function App() {\n  return \u003cReactP5Wrapper sketch={sketch} /\u003e;\n}\n```\n\n### TypeScript\n\nTypeScript sketches can be declared in two different ways, below you will find\ntwo ways to declare a sketch, both examples do the exact same thing.\n\nIn short though, the `ReactP5Wrapper` component requires you to pass a `sketch`\nprop. The `sketch` prop is simply a function which takes a `p5` instance as it's\nfirst and only argument.\n\n#### Option 1: Declaring a sketch using the `P5CanvasInstance` type\n\n```tsx\nimport * as React from \"react\";\nimport { P5CanvasInstance, ReactP5Wrapper } from \"@p5-wrapper/react\";\n\nfunction sketch(p5: P5CanvasInstance) {\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.draw = () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n}\n\nexport function App() {\n  return \u003cReactP5Wrapper sketch={sketch} /\u003e;\n}\n```\n\n#### Option 2: Declaring a sketch using the `Sketch` type\n\nUsing the `Sketch` type has one nice benefit over using `P5CanvasInstance` and\nthat is that the `p5` argument passed to the sketch function is auto-typed as a\n`P5CanvasInstance` for you.\n\n\u003e Side note:\n\u003e\n\u003e In general, it comes down to personal preference as to how you declare your\n\u003e sketches and there is nothing wrong with using the `P5CanvasInstance` manually\n\u003e in a regular `function` declaration.\n\n```tsx\nimport * as React from \"react\";\nimport { ReactP5Wrapper, Sketch } from \"@p5-wrapper/react\";\n\nconst sketch: Sketch = p5 =\u003e {\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.draw = () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n};\n\nexport function App() {\n  return \u003cReactP5Wrapper sketch={sketch} /\u003e;\n}\n```\n\n#### TypeScript Generics\n\nWe also support the use of Generics to add type definitions for your props. If\nused, the props will be properly typed when the props are passed to the\n`updateWithProps` method.\n\nTo utilise generics you can use one of two methods. In both of the examples\nbelow, we create a custom internal type called `MySketchProps` which is a union\ntype of `SketchProps` and a custom type which has a `rotation` key applied to\nit.\n\n\u003e Side note:\n\u003e\n\u003e We could also write the `MySketchProps` type as an interface to do exactly the\n\u003e same thing if that is to your personal preference:\n\u003e\n\u003e ```ts\n\u003e interface MySketchProps extends SketchProps {\n\u003e   rotation: number;\n\u003e }\n\u003e ```\n\nThis means, in these examples, that when the `rotation` prop that is provided as\npart of the `props` passed to the `updateWithProps` function, it will be\ncorrectly typed as a `number`.\n\n##### Usage with the `P5CanvasInstance` type\n\n```tsx\nimport {\n  P5CanvasInstance,\n  ReactP5Wrapper,\n  SketchProps\n} from \"@p5-wrapper/react\";\nimport React, { useEffect, useState } from \"react\";\n\ntype MySketchProps = SketchProps \u0026 {\n  rotation: number;\n};\n\nfunction sketch(p5: P5CanvasInstance\u003cMySketchProps\u003e) {\n  let rotation = 0;\n\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.updateWithProps = props =\u003e {\n    if (props.rotation) {\n      rotation = (props.rotation * Math.PI) / 180;\n    }\n  };\n\n  p5.draw = () =\u003e {\n    p5.background(100);\n    p5.normalMaterial();\n    p5.noStroke();\n    p5.push();\n    p5.rotateY(rotation);\n    p5.box(100);\n    p5.pop();\n  };\n}\n\nexport function App() {\n  const [rotation, setRotation] = useState(0);\n\n  useEffect(() =\u003e {\n    const interval = setInterval(\n      () =\u003e setRotation(rotation =\u003e rotation + 100),\n      100\n    );\n\n    return () =\u003e {\n      clearInterval(interval);\n    };\n  }, []);\n\n  return \u003cReactP5Wrapper sketch={sketch} rotation={rotation} /\u003e;\n}\n```\n\n##### Usage with the `Sketch` type\n\n```tsx\nimport { ReactP5Wrapper, Sketch, SketchProps } from \"@p5-wrapper/react\";\nimport React, { useEffect, useState } from \"react\";\n\ntype MySketchProps = SketchProps \u0026 {\n  rotation: number;\n};\n\nconst sketch: Sketch\u003cMySketchProps\u003e = p5 =\u003e {\n  let rotation = 0;\n\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.updateWithProps = props =\u003e {\n    if (props.rotation) {\n      rotation = (props.rotation * Math.PI) / 180;\n    }\n  };\n\n  p5.draw = () =\u003e {\n    p5.background(100);\n    p5.normalMaterial();\n    p5.noStroke();\n    p5.push();\n    p5.rotateY(rotation);\n    p5.box(100);\n    p5.pop();\n  };\n};\n\nexport function App() {\n  const [rotation, setRotation] = useState(0);\n\n  useEffect(() =\u003e {\n    const interval = setInterval(\n      () =\u003e setRotation(rotation =\u003e rotation + 100),\n      100\n    );\n\n    return () =\u003e {\n      clearInterval(interval);\n    };\n  }, []);\n\n  return \u003cReactP5Wrapper sketch={sketch} rotation={rotation} /\u003e;\n}\n```\n\n### Using abstracted setup and draw functions\n\n```jsx\nimport * as React from \"react\";\nimport { ReactP5Wrapper } from \"@p5-wrapper/react\";\n\nfunction setup(p5) {\n  return () =\u003e {\n    p5.createCanvas(600, 400, p5.WEBGL);\n  };\n}\n\nfunction draw(p5) {\n  return () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n}\n\nfunction sketch(p5) {\n  p5.setup = setup(p5);\n  p5.draw = draw(p5);\n}\n\nexport function App() {\n  return \u003cReactP5Wrapper sketch={sketch} /\u003e;\n}\n```\n\n### Props\n\nThe only required property of the `ReactP5Wrapper` component is the `sketch`\nprop. The `sketch` prop is a function that will be passed a p5 instance to use\nfor rendering your sketches as shown in [the usage section](#usage) above.\n\nYou can pass as many custom props as you want to the `ReactP5Wrapper` component\nand these will all be passed into the `updateWithProps` method if you have\ndefined it within your sketch.\n\n#### Reacting to props\n\nIn the below example you see the `updateWithProps` method being used. This is\ncalled when the component initially renders and when the props passed to the\nwrapper are changed, if it is set within your sketch. This way we can render our\n`ReactP5Wrapper` component and react to component prop changes directly within\nour sketches!\n\n```jsx\nimport { ReactP5Wrapper } from \"@p5-wrapper/react\";\nimport React, { useEffect, useState } from \"react\";\n\nfunction sketch(p5) {\n  let rotation = 0;\n\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.updateWithProps = props =\u003e {\n    if (props.rotation) {\n      rotation = (props.rotation * Math.PI) / 180;\n    }\n  };\n\n  p5.draw = () =\u003e {\n    p5.background(100);\n    p5.normalMaterial();\n    p5.noStroke();\n    p5.push();\n    p5.rotateY(rotation);\n    p5.box(100);\n    p5.pop();\n  };\n}\n\nexport function App() {\n  const [rotation, setRotation] = useState(0);\n\n  useEffect(() =\u003e {\n    const interval = setInterval(\n      () =\u003e setRotation(rotation =\u003e rotation + 100),\n      100\n    );\n\n    return () =\u003e {\n      clearInterval(interval);\n    };\n  }, []);\n\n  return \u003cReactP5Wrapper sketch={sketch} rotation={rotation} /\u003e;\n}\n```\n\n### Children\n\nTo render a component on top of the sketch, you can add it as a child of the\n`ReactP5Wrapper` component and then use the exported `P5WrapperClassName`\nconstant in your css-in-js library of choice to style one element above the\nother via css.\n\nFor instance, using [styled components](https://styled-components.com), we could\ncenter some text on top of our sketch like so:\n\n```jsx\nimport { P5WrapperClassName, ReactP5Wrapper } from \"@p5-wrapper/react\";\nimport styled, { createGlobalStyle } from \"styled-components\";\n\nconst GlobalWrapperStyles = createGlobalStyle`\n  .${P5WrapperClassName} {\n    position: relative;\n  }\n`;\n\nconst StyledCentredText = styled.span`\n  .${P5WrapperClassName} \u0026 {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n    color: white;\n    font-size: 2rem;\n    margin: 0;\n    text-align: center;\n  }\n`;\n\nexport function App() {\n  const [rotation, setRotation] = useState(0);\n\n  useEffect(() =\u003e {\n    const interval = setInterval(\n      () =\u003e setRotation(rotation =\u003e rotation + 100),\n      100\n    );\n\n    return () =\u003e {\n      clearInterval(interval);\n    };\n  }, []);\n\n  return (\n    \u003cFragment\u003e\n      \u003cGlobalWrapperStyles /\u003e\n      \u003cReactP5Wrapper sketch={sketch} rotation={rotation}\u003e\n        \u003cStyledCentredText\u003eHello world!\u003c/StyledCentredText\u003e\n      \u003c/ReactP5Wrapper\u003e\n    \u003c/Fragment\u003e\n  );\n}\n```\n\nOf course, you can also use any other css-in-js library or by just using simple\ncss to achieve almost anything you can imagine just by using the wrapper class\nas your root selector.\n\n### Fallback UIs\n\nLets say you want to have a fallback UI in case the `sketch` ever falls out of\nsync or is undefined for some reason. If this is a use case for you then you\ncall use the `fallback` prop to provide the necessary UI to show in the case\nthat the `sketch` becomes undefined. An example could be as follows:\n\n```jsx\nimport * as React from \"react\";\nimport { ReactP5Wrapper } from \"@p5-wrapper/react\";\n\nfunction sketchOne(p5) {\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.draw = () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n}\n\nfunction sketchTwo(p5) {\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.draw = () =\u003e {\n    p5.background(500);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n}\n\nexport function App() {\n  const [sketch, setSketch] = React.useState(undefined);\n  const chooseNothing = () =\u003e setSketch(undefined);\n  const chooseSketchOne = () =\u003e setSketch(sketchOne);\n  const chooseSketchTwo = () =\u003e setSketch(sketchTwo);\n\n  return (\n    \u003c\u003e\n      \u003cul\u003e\n        \u003cli\u003e\n          \u003cbutton onClick={chooseNothing}\u003eChoose nothing\u003c/button\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n          \u003cbutton onClick={chooseSketchOne}\u003eChoose sketch 1\u003c/button\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n          \u003cbutton onClick={chooseSketchTwo}\u003eChoose sketch 2\u003c/button\u003e\n        \u003c/li\u003e\n      \u003c/ul\u003e\n      \u003cReactP5Wrapper\n        fallback={\u003ch1\u003eNo sketch selected yet.\u003c/h1\u003e}\n        sketch={sketch}\n      /\u003e\n    \u003c/\u003e\n  );\n}\n```\n\nIn this case, by default the fallback UI containing\n`\u003ch1\u003eNo sketch selected yet.\u003c/h1\u003e` will be rendered, then if you select a\nsketch, it will be rendered until you choose to once again \"show nothing\" which\nfalls back to the fallback UI.\n\n### Error and Loading UIs\n\nSince version 4.4.0, it was possible to add a `fallback` prop, see the section\non fallbacks.\n\nSince version 5 it is now possible to pass an `error` and `loading` prop to the\nwrapper which allow the user to pass different UIs for error and loading states.\n\n- The `error` state will trigger if the sketch or the wrapper encounter an\n  issue, otherwise a default error view will be shown.\n- The `loading` state will trigger while the wrapper is being lazy loaded,\n  otherwise a default loading view will be shown.\n\n#### Error UIs\n\nTo show a custom UI when an error occurs within the sketch or the wrapper, you\ncan pass a lazy function to the `error` prop.\n\n```tsx\nimport * as React from \"react\";\nimport { P5CanvasInstance, ReactP5Wrapper } from \"@p5-wrapper/react\";\n\n// This child will throw an error, oh no!\nfunction ErrorChild() {\n  throw new Error(\"oops\");\n}\n\n// This view will catch the thrown error and give you access to what exactly was thrown.\nfunction ErrorUI(error: any) {\n  if (error instanceof Error) {\n    return \u003cp\u003eAn error occured: {error.message}\u003c/p\u003e;\n  }\n\n  return \u003cp\u003eAn unknown error occured: {error.toString()}\u003c/p\u003e;\n}\n\nfunction sketch(p5: P5CanvasInstance) {\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.draw = () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n}\n\nexport function App() {\n  return (\n    \u003cReactP5Wrapper sketch={sketch} error={ErrorUI}\u003e\n      \u003cErrorChild /\u003e\n    \u003c/ReactP5Wrapper\u003e\n  );\n}\n```\n\nInstead of the sketch, this will render `\u003cp\u003eAn error occured: oops\u003c/p\u003e`. Note\nthat in truth, the `ErrorView` will **always** receive `any` values since JS /\nTS allow you to `throw` whatever values you want to, this is why we have to add\nthe `error instanceof Error` check to be sure the value we got was actually an\n`Error` instance and not some other value like a `number`, `string`, `object` or\nanything else that could be thrown by JS / TS.\n\nAs mentioned above, the `error` state will trigger if the sketch or the wrapper\nencounter an issue, otherwise a default error view will be shown.\n\n#### Loading UIs\n\nTo show a custom UI while the sketch UI is being lazy loaded, you can pass a\nlazy function to the `loading` prop.\n\n```tsx\nimport * as React from \"react\";\nimport { P5CanvasInstance, ReactP5Wrapper } from \"@p5-wrapper/react\";\n\nfunction LoadingUI() {\n  return \u003cp\u003eThe sketch is being loaded.\u003c/p\u003e;\n}\n\nfunction sketch(p5: P5CanvasInstance) {\n  p5.setup = () =\u003e p5.createCanvas(600, 400, p5.WEBGL);\n\n  p5.draw = () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n}\n\nexport function App() {\n  return \u003cReactP5Wrapper sketch={sketch} loading={LoadingUI} /\u003e;\n}\n```\n\nIn the initial period between the sketch render starting and it's lazy loading\nending, the `LoadingUI` will be shown!\n\nAs mentioned above, the `loading` state will trigger while the wrapper is being\nlazy loaded, otherwise a default loading view will be shown.\n\n## P5 plugins and constructors\n\nAs discussed in multiple issues such as\n[#11](https://github.com/P5-wrapper/react/issues/11),\n[#23](https://github.com/P5-wrapper/react/issues/23),\n[#61](https://github.com/P5-wrapper/react/issues/61) and\n[#62](https://github.com/P5-wrapper/react/issues/62), there seems to be\nconfusion as to how we can use P5 plugins and constructors out of the box. This\nsection aims to clarify these!\n\n### Plugins\n\nSince P5 is being used in\n[P5 instance mode](https://github.com/processing/p5.js/wiki/Global-and-instance-mode)\nas part of this project, P5 will not automatically load global plugins like it\nusually might in global mode.\n\nLet's say we want to use the\n[P5 sound plugin](https://p5js.org/reference/#/libraries/p5.sound) in our\ncomponent, we could do the following:\n\n```tsx\nimport * as p5 from \"p5\";\nimport { ReactP5Wrapper, Sketch } from \"@p5-wrapper/react\";\nimport React, { useEffect, useState } from \"react\";\n\n(window as any).p5 = p5;\n\nawait import(\"p5/lib/addons/p5.sound\");\n\nconst sketch: Sketch = p5 =\u003e {\n  let song: p5.SoundFile;\n  let button: p5.Element;\n\n  p5.setup = () =\u003e {\n    p5.createCanvas(600, 400, p5.WEBGL);\n    p5.background(255, 0, 0);\n    button = p5.createButton(\"Toggle audio\");\n\n    button.mousePressed(() =\u003e {\n      if (!song) {\n        const songPath = \"/piano.mp3\";\n        song = p5.loadSound(\n          songPath,\n          () =\u003e {\n            song.play();\n          },\n          () =\u003e {\n            console.error(\n              `Could not load the requested sound file ${songPath}`\n            );\n          }\n        );\n        return;\n      }\n\n      if (!song.isPlaying()) {\n        song.play();\n        return;\n      }\n\n      song.pause();\n    });\n  };\n\n  p5.draw = () =\u003e {\n    p5.background(250);\n    p5.normalMaterial();\n    p5.push();\n    p5.rotateZ(p5.frameCount * 0.01);\n    p5.rotateX(p5.frameCount * 0.01);\n    p5.rotateY(p5.frameCount * 0.01);\n    p5.plane(100);\n    p5.pop();\n  };\n};\n\nexport default function App() {\n  return \u003cReactP5Wrapper sketch={sketch} /\u003e;\n}\n```\n\nIn this Typescript + React example, we can see a few key things.\n\n- Firstly we need to set `p5` on the `window` object manually. This is because\n  `p5.sound` requires that it be executed client side only AND that `p5` be\n  available BEFORE it is imported into the global (`window`) scope.\n- Secondly, we ensure that audio is played after a user action, in our case this\n  happens on a button click. This is because in some browsers, without waiting\n  for a user interaction before playing audio, the audio will be blocked by the\n  browser from playing at all.\n- Thirdly and relevant especially to Safari users, Safari blocks audio from all\n  tabs by default, you will need to manually change this setting in your Safari\n  settings. This could affect other browsers but sadly this is a browser\n  decision and until [P5 Sound](https://github.com/processing/p5.js-sound) is\n  updated to support newer audio APIs and browser requirements. This could\n  happen at anytime in other places and is a\n  [P5 Sound](https://github.com/processing/p5.js-sound) issue most generally\n  because it does not ask for permissions by default, even though browsers have\n  been requiring it for some time.\n\n\u003e **Note:** The above example requires support for\n\u003e [top level await](https://caniuse.com/mdn-javascript_operators_await_top_level),\n\u003e [dynamic import statements](https://caniuse.com/es6-module-dynamic-import) and\n\u003e [the stream API](https://caniuse.com/stream) to be supported in your browser.\n\u003e Furthermore, [the stream API](https://caniuse.com/stream) built into the\n\u003e browser requires that HTTPS is used to ensure secure data transmission.\n\n### Constructors\n\nTo access P5 constructors such as `p5.Vector` or `p5.Envelope`, you need to use\nthe instance mode syntax instead. For example:\n\n| Constructor | Global mode accessor | Instance mode accessor  |\n| ----------- | -------------------- | ----------------------- |\n| Vector      | p5.Vector            | p5.constructor.Vector   |\n| Envelope    | p5.Envelope          | p5.constructor.Envelope |\n\nSo now that we know this, let's imagine we want a random 2D Vector instance. In\nour `sketch` function we would simply call `p5.constructor.Vector.random2D()`\ninstead of `p5.Vector.random2D()`. This is because of how the\n[P5 instance mode](https://github.com/processing/p5.js/wiki/Global-and-instance-mode)\nwas implemented by the P5 team. While I am not sure why they decided to change\nthe API for instance mode specifically, it is still quite simple to use the\nconstructs we are used to without much extra work involved.\n\n## Development\n\n**NOTE:** The source code for the component is in the `src` directory.\n\nTo build, watch and serve the examples which will also watch the component\nsource, run:\n\n```sh\n  pnpm preview\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp5-wrapper%2Freact","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp5-wrapper%2Freact","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp5-wrapper%2Freact/lists"}