UNPKG

@playcanvas/react

Version:

A React renderer for PlayCanvas – build interactive 3D applications using React's declarative paradigm.

77 lines 2.87 kB
import { useEffect, useRef } from 'react'; import { useParent } from "./use-parent.js"; import { useApp } from "./use-app.js"; /** * This hook is used to create a script component on an entity. * @param scriptConstructor - The constructor for the script. * @param props - The props for the script. * * @example * const script = useScript(MyScript, { * myProperty: 'value', * }); */ export const useScript = (scriptConstructor, props, ref) => { const parent = useParent(); const app = useApp(); const scriptName = toLowerCamelCase(scriptConstructor.name); const scriptRef = useRef(null); const scriptComponentRef = useRef(null); // Create the script synchronously useEffect(() => { if (!app) return; // Ensure the parent entity has a script component if (!parent.script) { parent.addComponent('script'); } // Check if we've already created the script if (!scriptRef.current) { // Create the script instance with the provided attributes const scriptComponent = parent.script; const scriptInstance = scriptComponent.create(scriptConstructor, { properties: { ...props }, preloading: false, }); if (ref) { if (typeof ref === 'function') { ref(scriptInstance); } else { ref.current = scriptInstance; } } scriptRef.current = scriptInstance; scriptComponentRef.current = scriptComponent; } // Cleanup function to remove the script when the component is unmounted return () => { const scriptComponent = scriptComponentRef.current; const script = scriptRef.current; scriptRef.current = null; scriptComponentRef.current = null; if (app && app.root && script && scriptComponent) { scriptComponent.destroy(scriptName); if (ref) { if (typeof ref === 'function') { ref(null); } else { ref.current = null; } } } }; }, [app, parent, scriptConstructor]); // Update script props when they change useEffect(() => { const script = scriptRef.current; // Ensure componentRef.current exists before updating props if (!script) return; const filteredProps = Object.fromEntries(Object.entries(props).filter(([key]) => key in script)); Object.assign(script, filteredProps); }, [props]); }; const toLowerCamelCase = (str) => str[0].toLowerCase() + str.substring(1); //# sourceMappingURL=use-script.js.map