# Needle Engine — Framework Integration ## React ### Listen for 3D events in a component ```tsx import { useEffect, useState } from "react"; function ScoreDisplay() { const [score, setScore] = useState(0); useEffect(() => { const ne = document.querySelector("needle-engine"); const handler = (e: CustomEvent) => setScore(e.detail.score); ne?.addEventListener("score-changed", handler as EventListener); return () => ne?.removeEventListener("score-changed", handler as EventListener); }, []); return
Score: {score}
; } ``` ### Call into the 3D scene from React ```tsx function GameControls() { const addScore = async () => { const { findObjectOfType } = await import("@needle-tools/engine"); const { MyScoreManager } = await import("./scripts/MyScoreManager.js"); findObjectOfType(MyScoreManager)?.addScore(10); }; return ; } ``` ### Use engine hooks from React ```tsx useEffect(() => { import("@needle-tools/engine").then(({ onStart }) => { onStart((ctx) => { // safe to access components here }); }); }, []); ``` --- ## Svelte / SvelteKit ```svelte

Score: {score}

``` --- ## Vue / Nuxt ```vue ``` --- ## Vanilla JS / No Framework ```html ``` --- ## Engine Hooks Reference These standalone functions from `@needle-tools/engine` mirror the component lifecycle but work outside of a class: | Hook | When it fires | |---|---| | `onInitialized(cb)` | Once after context creation and first content load | | `onStart(cb)` | Once when the context/scene is ready | | `onUpdate(cb)` | Every frame (before rendering) | | `onBeforeRender(cb)` | Just before Three.js renders | | `onAfterRender(cb)` | Just after Three.js renders | | `onClear(cb)` | Before context is cleared (e.g. when `src` changes) | | `onDestroy(cb)` | When the context is torn down | All callbacks receive `(ctx: Context)` as their argument. ### Client-only (no SSR) When server-side rendering is **disabled**, import and call hooks directly: ```ts import { onStart, onUpdate, onBeforeRender, onDestroy } from "@needle-tools/engine"; onStart((ctx) => { /* setup */ }); onUpdate((ctx) => { /* per-frame logic */ }); onDestroy((ctx) => { /* cleanup */ }); ``` ### With SSR (Next.js, SvelteKit, Nuxt, etc.) `@needle-tools/engine` depends on WebGL / browser APIs and **cannot be imported on the server**. Use a dynamic import so the module is only loaded client-side (same pattern as with any three.js-based engine): ```ts import("@needle-tools/engine").then(({ onStart, onUpdate, onDestroy }) => { onStart((ctx) => { /* setup */ }); onUpdate((ctx) => { /* per-frame logic */ }); onDestroy((ctx) => { /* cleanup */ }); }); ```