|
1 | 1 | import diff from "microdiff"; |
2 | 2 | import p5 from "p5"; |
3 | | -import React, { createRef, FC, memo, useState } from "react"; |
| 3 | +import React, { createRef, FC, memo, MutableRefObject, useRef } from "react"; |
4 | 4 | import { useIsomorphicEffect } from "rooks"; |
5 | 5 |
|
6 | 6 | type Wrapper = HTMLDivElement; |
7 | | - |
8 | | -export interface SketchProps { |
| 7 | +export type Sketch = (instance: P5CanvasInstance) => void; |
| 8 | +export type SketchProps = { |
9 | 9 | [key: string]: any; |
10 | | -} |
11 | | - |
12 | | -export interface Sketch { |
13 | | - (instance: P5Instance): void; |
14 | | -} |
15 | | - |
16 | | -export interface P5WrapperProps extends SketchProps { |
| 10 | +}; |
| 11 | +export type P5WrapperProps = SketchProps & { |
17 | 12 | sketch: Sketch; |
18 | | -} |
19 | | - |
20 | | -export interface P5Instance extends p5 { |
| 13 | +}; |
| 14 | +export type P5CanvasInstance = p5 & { |
21 | 15 | updateWithProps?: (props: SketchProps) => void; |
22 | | -} |
| 16 | +}; |
| 17 | + |
| 18 | +// @TODO: remove in next major version, keep for compatibility reasons for now. |
| 19 | +export type P5Instance = P5CanvasInstance; |
23 | 20 |
|
24 | | -function createCanvas(sketch: Sketch, wrapper: Wrapper): P5Instance { |
| 21 | +function createCanvasInstance( |
| 22 | + sketch: Sketch, |
| 23 | + wrapper: Wrapper |
| 24 | +): P5CanvasInstance { |
25 | 25 | return new p5(sketch, wrapper); |
26 | 26 | } |
27 | 27 |
|
| 28 | +function removeCanvasInstance( |
| 29 | + canvasInstanceRef: MutableRefObject<P5CanvasInstance | undefined> |
| 30 | +) { |
| 31 | + canvasInstanceRef.current?.remove(); |
| 32 | + canvasInstanceRef.current = undefined; |
| 33 | +} |
| 34 | + |
28 | 35 | const ReactP5WrapperComponent: FC<P5WrapperProps> = ({ |
29 | 36 | sketch, |
30 | 37 | children, |
31 | 38 | ...props |
32 | 39 | }) => { |
33 | 40 | const wrapperRef = createRef<Wrapper>(); |
34 | | - const [instance, setInstance] = useState<P5Instance>(); |
| 41 | + const canvasInstanceRef = useRef<P5CanvasInstance>(); |
35 | 42 |
|
36 | 43 | useIsomorphicEffect(() => { |
37 | 44 | if (wrapperRef.current === null) { |
38 | 45 | return; |
39 | 46 | } |
40 | 47 |
|
41 | | - instance?.remove(); |
42 | | - const canvas = createCanvas(sketch, wrapperRef.current); |
43 | | - setInstance(canvas); |
| 48 | + removeCanvasInstance(canvasInstanceRef); |
| 49 | + canvasInstanceRef.current = createCanvasInstance( |
| 50 | + sketch, |
| 51 | + wrapperRef.current |
| 52 | + ); |
44 | 53 | }, [sketch]); |
45 | 54 |
|
46 | | - useIsomorphicEffect(() => { |
47 | | - instance?.updateWithProps?.(props); |
48 | | - }, [props, instance]); |
| 55 | + useIsomorphicEffect( |
| 56 | + () => canvasInstanceRef.current?.updateWithProps?.(props), |
| 57 | + [props] |
| 58 | + ); |
49 | 59 |
|
50 | | - useIsomorphicEffect(() => () => instance?.remove(), []); |
| 60 | + useIsomorphicEffect(() => () => removeCanvasInstance(canvasInstanceRef), []); |
51 | 61 |
|
52 | 62 | return <div ref={wrapperRef}>{children}</div>; |
53 | 63 | }; |
|
0 commit comments