Skip to content

Commit

Permalink
fix: 796 unmount the canvas component instant mount children again ev…
Browse files Browse the repository at this point in the history
…en if canvas is not mounted (#799)

* fix: avoid mounting again custom renderer components on TresCanvas unmounted

* chore: fix lint
  • Loading branch information
alvarosabu authored Aug 15, 2024
1 parent 3fadeed commit 9a20b52
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 11 deletions.
5 changes: 3 additions & 2 deletions playground/src/pages/basic/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { TresCanvas, useRenderLoop } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
const state = reactive({
clearColor: '#201919',
clearColor: '#ffffff',
shadows: true,
alpha: false,
Expand All @@ -24,7 +24,7 @@ onLoop(({ elapsed }) => {
sphereRef.value.position.y += Math.sin(elapsed) * 0.01
// Update events without needing the mouse to move
canvasRef.value?.context?.eventManager.forceUpdate()
canvasRef.value?.context?.eventManager?.forceUpdate()
})
function onPointerEnter(ev) {
Expand All @@ -50,6 +50,7 @@ const toonTealMaterial = new MeshToonMaterial({
type="checkbox"
/>
<TresCanvas
v-if="sphereExists"
ref="canvasRef"
v-bind="state"
@render="onRender"
Expand Down
21 changes: 21 additions & 0 deletions playground/src/pages/issues/796/TheBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- eslint-disable no-console -->
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
console.log('BOX--INIT:', Date.now())
onMounted(() => {
console.log('BOX--MOUNTED', Date.now())
})
onUnmounted(() => {
console.log('BOX--UNMOUNTED', Date.now())
})
</script>

<template>
<TresMesh>
<TresBoxGeometry />
<TresMeshNormalMaterial />
</TresMesh>
</template>
8 changes: 8 additions & 0 deletions playground/src/pages/issues/796/TheExperience.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script setup lang="ts">
import TheBox from './TheBox.vue'
</script>

<template>
<TresPerspectiveCamera :position="[5, 5, 5]" :look-at="[0, 0, 0]" />
<TheBox />
</template>
22 changes: 22 additions & 0 deletions playground/src/pages/issues/796/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import TheExperience from './TheExperience.vue'
const gl = {
clearColor: '#82DBC5',
shadows: true,
alpha: false,
}
const showCanvas = ref(true)
</script>

<template>
<input
v-model="showCanvas"
type="checkbox"
/>
<TresCanvas v-if="showCanvas" v-bind="gl">
<TheExperience />
</TresCanvas>
</template>
6 changes: 6 additions & 0 deletions playground/src/router/routes/issues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,10 @@ export const issuesRoutes = [
name: '#749: attach-detach',
component: () => import('../../pages/issues/749/index.vue'),
},
{
path: '/issues/796',
name: '#796: unmounted',
component: () => import('../../pages/issues/796/index.vue'),
},

]
25 changes: 16 additions & 9 deletions src/components/TresCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ const scene = shallowRef<TresScene | Scene>(new Scene())
const instance = getCurrentInstance()?.appContext.app
extend(THREE)
const createInternalComponent = (context: TresContext) =>
const createInternalComponent = (context: TresContext, empty = false) =>
defineComponent({
setup() {
const ctx = getCurrentInstance()?.appContext
Expand All @@ -121,12 +121,12 @@ const createInternalComponent = (context: TresContext) =>
if (typeof window !== 'undefined') {
registerTresDevtools(ctx?.app, context)
}
return () => h(Fragment, null, slots?.default ? slots.default() : [])
return () => h(Fragment, null, !empty ? slots.default() : [])
},
})
const mountCustomRenderer = (context: TresContext) => {
const InternalComponent = createInternalComponent(context)
const mountCustomRenderer = (context: TresContext, empty = false) => {
const InternalComponent = createInternalComponent(context, empty)
const { render } = createRenderer(nodeOps(context))
render(h(InternalComponent), scene.value as unknown as TresObject)
}
Expand All @@ -141,7 +141,6 @@ const dispose = (context: TresContext, force = false) => {
(scene.value as TresScene).__tres = {
root: context,
}
mountCustomRenderer(context)
}
const disableRender = computed(() => props.disableRender)
Expand All @@ -150,6 +149,16 @@ const context = shallowRef<TresContext | null>(null)
defineExpose({ context, dispose: () => dispose(context.value as TresContext, true) })
const handleHMR = (context: TresContext) => {
dispose(context)
mountCustomRenderer(context)
}
const unmountCanvas = () => {
dispose(context.value as TresContext)
mountCustomRenderer(context.value as TresContext, true)
}
onMounted(() => {
const existingCanvas = canvas as Ref<HTMLCanvasElement>
Expand Down Expand Up @@ -209,12 +218,10 @@ onMounted(() => {
}
// HMR support
if (import.meta.hot && context.value) { import.meta.hot.on('vite:afterUpdate', () => dispose(context.value as TresContext)) }
if (import.meta.hot && context.value) { import.meta.hot.on('vite:afterUpdate', () => handleHMR(context.value as TresContext)) }
})
onUnmounted(() => {
dispose(context.value as TresContext)
})
onUnmounted(unmountCanvas)
</script>

<template>
Expand Down

0 comments on commit 9a20b52

Please sign in to comment.