diff --git a/packages/fiber/src/core/renderer.ts b/packages/fiber/src/core/renderer.ts index c83e84e066..6103141565 100644 --- a/packages/fiber/src/core/renderer.ts +++ b/packages/fiber/src/core/renderer.ts @@ -212,7 +212,7 @@ function createRenderer(_roots: Map, _getEventPriority?: // Since disposal is recursive, we can check the optional dispose arg, which will be undefined // when the reconciler calls it, but then carry our own check recursively const isPrimitive = child.__r3f?.primitive - const shouldDispose = dispose === undefined ? child.dispose !== null && !isPrimitive : dispose + const shouldDispose = !isPrimitive && (dispose === undefined ? child.dispose !== null : dispose) // Remove nested child objects. Primitives should not have objects and children that are // attached to them declaratively ... diff --git a/packages/fiber/tests/core/renderer.test.tsx b/packages/fiber/tests/core/renderer.test.tsx index e24b19abfa..f970670a38 100644 --- a/packages/fiber/tests/core/renderer.test.tsx +++ b/packages/fiber/tests/core/renderer.test.tsx @@ -962,4 +962,22 @@ describe('renderer', () => { expect(ref.current!.children).toStrictEqual([child1, child.current]) expect(ref.current!.userData.attach).toBe(attachedChild.current) }) + + // TODO: scheduler isn't flushed during testing which prevents disposal + it.skip('should not recursively dispose of attached primitives', async () => { + const meshDispose = jest.fn() + const primitiveDispose = jest.fn() + + await act(async () => + root.render( + + + , + ), + ) + await act(async () => root.render(null)) + + expect(meshDispose).toBeCalledTimes(1) + expect(primitiveDispose).not.toBeCalled() + }) })