javascript - React component is duplicated with p5.js canvas - Stack Overflow

I'm trying to create a React app with a single p5.js sketch. However, the ponent containing the p5

I'm trying to create a React app with a single p5.js sketch. However, the ponent containing the p5 sketch is being duplicated on my page. Not sure why it would be rendered this way.

Here you can see the code: .tsx,Sketch.tsx,index.tsx

Here are the react ponents definition:

App.tsx

import React = require('react');
import Sketch from './Sketch';

function App() {
  return (
    <div className="App">
      <Sketch />
    </div>
  );
}

export default App;

Sketch.tsx

import React = require('react');
import { useEffect } from 'react';
import p5 from 'p5';

const Sketch = () => {
  const p = (p5: any) => {
    let radius: number;
    p5.setup = () => {
      p5.createCanvas(p5.windowWidth / 2, p5.windowHeight / 2);
      p5.background(0);
      radius = 0;
    };

    p5.draw = () => {
      p5.ellipse(p5.width / 2, p5.height / 2, radius, radius);
      if (radius < 70) radius++;
    };
  };

  useEffect(() => {
    new p5(p);
  }, []);

  return <></>;
};

export default Sketch;

index.tsx

import * as React from 'react';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import App from './App';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

What could I be missing here?

I'm trying to create a React app with a single p5.js sketch. However, the ponent containing the p5 sketch is being duplicated on my page. Not sure why it would be rendered this way.

Here you can see the code: https://stackblitz./edit/react-ts-kocwqw?file=App.tsx,Sketch.tsx,index.tsx

Here are the react ponents definition:

App.tsx

import React = require('react');
import Sketch from './Sketch';

function App() {
  return (
    <div className="App">
      <Sketch />
    </div>
  );
}

export default App;

Sketch.tsx

import React = require('react');
import { useEffect } from 'react';
import p5 from 'p5';

const Sketch = () => {
  const p = (p5: any) => {
    let radius: number;
    p5.setup = () => {
      p5.createCanvas(p5.windowWidth / 2, p5.windowHeight / 2);
      p5.background(0);
      radius = 0;
    };

    p5.draw = () => {
      p5.ellipse(p5.width / 2, p5.height / 2, radius, radius);
      if (radius < 70) radius++;
    };
  };

  useEffect(() => {
    new p5(p);
  }, []);

  return <></>;
};

export default Sketch;

index.tsx

import * as React from 'react';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import App from './App';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

What could I be missing here?

Share Improve this question edited May 23, 2022 at 13:32 chris asked May 23, 2022 at 13:27 chrischris 2,8504 gold badges37 silver badges66 bronze badges 1
  • When the Sketch ponent is first mounted, it makes one canvas. It then gets unmounted and mounted again. That way, the p function is ran twice. You should return a cleanup function in your useEffect call to remove the created canvas somehow. – madzong Commented May 23, 2022 at 13:48
Add a ment  | 

2 Answers 2

Reset to default 6

Solution was to remove <StrictMode> from index.tsx.

From the docs,

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking...

Looks like Strict Mode is a safeguard to detect side effects.

Another solution without removing the strict mode can be found here

https://www.lloydatkinson/posts/2022/how-to-prevent-a-duplicated-canvas-when-using-p5-and-react-strict-mode/

Basically using the useEffect cleanup method the current p5 instance will be deleted and a new one will be created on the next hot reload.

Here is a working example:

import { useEffect, useRef } from "react";
import p5 from "p5";

function App() {
  const p5Ref = useRef();

  const Sketch = (p) => {
    p.setup = () => {
      p.createCanvas(500, 400);
    };

    p.draw = () => {
      p.background(200);
      p.rect(p.mouseX, p.mouseY, 100, 100);
    };
  };

  useEffect(() => {
    const mp5 = new p5(Sketch, p5Ref.current);
    return mp5.remove;
  }, []);

  return <div ref={p5Ref}></div>;
}

export default App;

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745290186a4620808.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信