dataarts / dat.gui

Lightweight controller library for JavaScript.
Apache License 2.0
7.46k stars 1.08k forks source link

Duplicated GUI with vite + react + three.js #323

Open Creative-Ataraxia opened 1 year ago

Creative-Ataraxia commented 1 year ago

I'm trying to use dat.gui with vite + react + tailwind + three.js:

function App() {
  useEffect(() => {
    const gui = new dat.GUI({ width: 400 })
    gui.add(..etc..)

  return (
    <>
      <canvas className='fixed top-0 left-0 outline-none' id="MyCanvas" />
    </>
  )
}

but the gui is duplicated, showing another panel on the back: 1 and if I click on open, it will open two sets of controls like so: 2 one set of control do work as intended, the other set does not work at all;

I've tried to pass the autoPlace: false but then the gui won't show up at all anymore

any help is much appreciated

edit: also each time vite re-render's the page, a new set of gui is added to the viewport: 3 so it will become unusable like this: 4

do I have to unmount gui after each render somehow? btw, I'm putting all the three.js code in a useEffect() hook to be able to render it via react..

edit2: so on a first glance this seeks to be an issue of gui.dat not dismounting and/or removing the last <div> created on the dom when vite rebuilds the build as I save code changes in the IDE; does dat.gui have a built-in API to remove the last created DOM element?

rickyzhangca commented 1 year ago

can confirm this happening on vite + react

lesha-co commented 9 months ago

or you can put gui in a ref or you can call gui.destroy() in useEffect return (just make sure it doesn't trigger unless needed to)

anyway this looks more like react issue than library issue

Kvisaz commented 8 months ago

It is normal behavior for useEffect with creation/subscription

To avoid bugs - always use return in useEffect

We need return some callback to unsubscribe, to destroy etc....

useEffect(() => {
    const gui = new dat.GUI({ width: 400 })
    gui.add(..etc..)
    return ()=> gui.destroy()
  }