diff --git a/.changeset/gsplat-props-guard.md b/.changeset/gsplat-props-guard.md new file mode 100644 index 00000000..04c987a7 --- /dev/null +++ b/.changeset/gsplat-props-guard.md @@ -0,0 +1,6 @@ +--- +"@playcanvas/react": patch +--- + +Fixed GSplat component props re-application causing splat to disappear during React re-renders. Added equality guards for `instance` and `material` properties to prevent destructive setter calls when the value hasn't changed. + diff --git a/packages/lib/src/components/GSplat.tsx b/packages/lib/src/components/GSplat.tsx index 1eaa637f..902cabe6 100644 --- a/packages/lib/src/components/GSplat.tsx +++ b/packages/lib/src/components/GSplat.tsx @@ -2,7 +2,7 @@ import { FC } from "react"; import { useComponent } from "../hooks/index.ts"; -import { Asset, Entity, GSplatComponent } from "playcanvas"; +import { Asset, Entity, GSplatComponent, GSplatInstance, ShaderMaterial } from "playcanvas"; import { PublicProps } from "../utils/types-utils.ts"; import { validatePropsWithDefaults, createComponentDefinition, getStaticNullApplication } from "../utils/validation.ts"; /** @@ -60,5 +60,31 @@ componentDefinition.schema = { instance.unified = value; instance.enabled = true; } + }, + material: { + validate: (val: unknown) => val === null || val instanceof ShaderMaterial, + errorMsg: (val: unknown) => `Invalid value for prop "material": "${val}". Expected a ShaderMaterial or null.`, + default: null, + apply: (instance: GSplatComponent, props: Record, key: string) => { + const value = props[key] as ShaderMaterial | null; + if (instance.material === value) { + return; + } + if (value) { + instance.material = value; + } + } + }, + instance: { + validate: (val: unknown) => val === null || val instanceof GSplatInstance, + errorMsg: (val: unknown) => `Invalid value for prop "instance": "${val}". Expected a GSplatInstance or null.`, + default: null, + apply: (instance: GSplatComponent, props: Record, key: string) => { + const value = props[key] as GSplatInstance | null; + if (instance.instance === value) { + return; + } + instance.instance = value; + } } }