# R3F dispose not working (memory is not reduced)

**URL:** <https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924>\
**Category:** Questions\
**Tags:** r3f, react-three-fiber\
**Created:** [February 12, 2023, 4:53am UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924 "2023-02-12T04:53:06Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![waynewu](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/waynewu/32/32300_2.png) [@waynewu](https://discourse.threejs.org/u/waynewu)\
**Post date:** [February 12, 2023, 4:53am UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/1 "2023-02-12T04:53:06Z")

</div>

With React conditional rendering, I removed the `GLTFModel`, but memory is not reduced.

```javascript
// model with GLTF
function GLTFModel(...) { ... }

// GLTF container
function GLTFContainer() {
  const [show, setShow] = useState(true)
  return show 
            ? <GLTFModel onClick={() => setShow(false) } 
            : <group />
}

```

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [February 12, 2023, 9:25am UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/2 "2023-02-12T09:25:18Z")

</div>

Fiber Auto disposes, with the exception of primitive. Primitive points to a foreign object that you or something else control, it can’t just go and destroy it. You can dispose yourself if you control the object yourself.

On top of that all loaders are cached, two useGLTF with the same url will return the same object data, it won’t load or parse twice, but after unmount the cached data is still there.

You have access to the cache and can clear it but usually that’s a rare use case. Most webgl projects will load all assets up front and do not mount or change them runtime, because mounting in threejs is very expensive. Could you describe what you want to do?

---

<div class="post-metadata">

**Author:** ![waynewu](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/waynewu/32/32300_2.png) [@waynewu](https://discourse.threejs.org/u/waynewu)\
**Post date:** [February 12, 2023, 3:35pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/3 "2023-02-12T15:35:15Z")

</div>

Thank you for your reply, I do this because we have the feature to switch between 2D/3D styles. Maybe I can refresh the page, but need to keep all the use state.

 ![CleanShot 2023-02-12 at 23.32.12@2x](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/d/8/d83e19e21ec0d09cf4ff2f4d8ff89bdbe752c96c.jpeg)

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [February 12, 2023, 3:38pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/4 "2023-02-12T15:38:39Z")

</div>

all loader hooks use this library [GitHub - pmndrs/suspend-react: 🚥 Async/await for React components](https://github.com/pmndrs/suspend-react) it gives you cache control. you can clear stuff out with it. clear is also available on all the hooks.

```plaintext
useLoader.clear(GLTFLoader, url)
useGLTF.clear(url)

```

otherwise you can also use GLTFLoader/TextureLoader directly and handle assets any way you want.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [February 12, 2023, 3:40pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/5 "2023-02-12T15:40:11Z")

</div>

i would also suggest using gltfjsx --transform to compress models and textures. or better yet use ktx2. if you’re dealing with such an amount of data that you need to clear cache that probably points to a lot of excess data.

---

<div class="post-metadata">

**Author:** ![waynewu](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/waynewu/32/32300_2.png) [@waynewu](https://discourse.threejs.org/u/waynewu)\
**Post date:** [February 12, 2023, 3:47pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/6 "2023-02-12T15:47:57Z")

</div>

I have questions, my understanding is that `gltfjsx` is for specific models, predefined. But my models is hosting on the server, I can only get their urls and names, then I use `useGLTF` or `useLoader` to load them. In my case, does `gltfjsx` works?

---

<div class="post-metadata">

**Author:** ![waynewu](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/waynewu/32/32300_2.png) [@waynewu](https://discourse.threejs.org/u/waynewu)\
**Post date:** [February 12, 2023, 3:50pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/7 "2023-02-12T15:50:53Z")

</div>

Do you mean GLTF models in `<primitive>...</primitive>` will not be disposed automatically? Here is my `Model3D` code:

```javascript
import { useGLTF } from "@react-three/drei";
import { ThreeEvent } from "@react-three/fiber";
import { Suspense } from "react";

type Model3DEvent = (
  event: ThreeEvent<MouseEvent>,
  model: THREE.Object3D
) => void;

type Model3DProps = {
  url?: string;
  position?: [number, number, number];
  visible?: boolean;
  children?: React.ReactNode;
  onClick?: Model3DEvent;
  onPointerOver?: Model3DEvent;
  onPointerOut?: Model3DEvent;
};

export default function Model3D(props: Model3DProps) {
  return <Suspense>{props.url && <_Model3D {...props} />}</Suspense>;
}

function _Model3D(props: Model3DProps) {
  const { scene } = useGLTF(props.url!);
  return scene ? (
    <primitive
      object={scene}
      position={props.position}
      visible={props.visible}
      onClick={(e: ThreeEvent<MouseEvent>) => {
        props.onClick && props.onClick(e, scene);
      }}
      onPointerOver={(e: ThreeEvent<MouseEvent>) => {
        props.onPointerOver && props.onPointerOver(e, scene);
      }}
      onPointerOut={(e: ThreeEvent<MouseEvent>) => {
        props.onPointerOut && props.onPointerOut(e, scene);
      }}
    >
      {props.children}
    </primitive>
  ) : (
    <group />
  );
}

```

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [February 12, 2023, 5:10pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/8 "2023-02-12T17:10:40Z")

</div>

useGLTF(props.url!) fetches a url, gltfloader parses it, the data is cached, it will never be deleted (unless you call useGLTF.clear on the same url

primitive will never call dispose, because the object it mounts is not declarative, it exists outside of react, therefore it won’t destroy it.

if you want, call dispose and then useGLTF.clear on unmount.

---

<div class="post-metadata">

**Author:** ![waynewu](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/waynewu/32/32300_2.png) [@waynewu](https://discourse.threejs.org/u/waynewu)\
**Post date:** [February 13, 2023, 1:35am UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/9 "2023-02-13T01:35:44Z")

</div>

Thank you again, I will try this way. According to the official documentation [Loading Models](https://docs.pmnd.rs/react-three-fiber/tutorials/loading-models), models are always hosted in `primitive`, do I have the other way to add a model with auto disposal?

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [February 13, 2023, 9:59am UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/10 "2023-02-13T09:59:43Z")

</div>

every mesh or object that isn’t a primitive

```plaintext
<mesh /> // <---- this gets removed and disposed of on unmount
<group /> // <---- this gets removed and disposed of on unmount
<orbitControls /> // <---- this gets removed and disposed of on unmount
<foo /> // <---- this gets removed and disposed of on unmount

```

otherwise you have useEffect, cache clear and a special dispose that traverses the object since dispose in threejs is not really that easy to do by hand, i believe scene.dispose() will do nothing even.

```plaintext
import { dispose } from '@react-three/fiber'

const { scene } = useGLTF(url)
useEffect(() => {
  ...
  return () => {
    dispose(scene)
    useGLTF.clear(url)
  }
}, [url])

```

keep in mind that by doing so if you mount the model again it will have to parse again, it would be massively wasteful. i would only recommend that when things don’t go onto the screen ever.

ps, i would also use gltfjsx instead of a primitive. looks weird to me to use a primitive object={scene}, which already has children, and then overwrite children like that. it probably works but seems sketchy. with gltfjsx you can also omit the “dispose={null}” that it attaches on the root mesh, if you remove it it will dispose the whole scene automatically since none of it is a primitive. you still need to do the cache clear because the model is essentially destroyed on unmount.

---

<div class="post-metadata">

**Author:** ![Lawrence3DPK](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/lawrence3dpk/32/29184_2.png) [@Lawrence3DPK](https://discourse.threejs.org/u/Lawrence3DPK)\
**Post date:** [November 15, 2023, 8:39pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/11 "2023-11-15T20:39:55Z")

</div>

@drcmda do would you know if `useGLTF` automatically uses `useMemo` internally in order to memoize geometries and materials preventing regeneration when rerendering or would that be handled manually?

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [November 15, 2023, 8:52pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/12 "2023-11-15T20:52:07Z")

</div>

it uses suspense, there’s no useMemo.

```jsx
function Foo() {
  const data = useGLTF("baz.glb")
  ...

function Bar() {
  const data = useGLTF("baz.glb")
  ...

```

both access the same exact data, the glb is loaded only once.

---

<div class="post-metadata">

**Author:** ![Lawrence3DPK](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/lawrence3dpk/32/29184_2.png) [@Lawrence3DPK](https://discourse.threejs.org/u/Lawrence3DPK)\
**Post date:** [November 15, 2023, 9:03pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/13 "2023-11-15T21:03:48Z")

</div>

Yes I understood that from the thread above and fwiu suspense is to wait for the model to load, I guess my question is slightly different from the OP’s, does `useGLTF` behave in the same way that `useMemo` for the geometries and materials part of the file in the same way as…

```javascript
const geo = useMemo(() => {
  return new THREE.BufferGeometry()
} 

```

so that the geometry and materials associated aren’t recreated ever render eg when the model is hovered for instance?

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [November 15, 2023, 9:09pm UTC](https://discourse.threejs.org/t/r3f-dispose-not-working-memory-is-not-reduced/47924/14 "2023-11-15T21:09:21Z")

</div>

useMemo memoizes at the component level, two components memoizing a thing will execute twice. suspense is global memoization. the geometries and materials that useGLTF returns are the same where ever it’s called, given that it’s being called with the same key (the url). they aren’t re-created, they are always re-used.
