Basics

App Structure

Threlte makes heavy use of Svelte’s Context API as a way to pass data through the component tree without having to pass props down manually at every level:

SomeComponent.svelte
<script>
  const { camera, renderer } = useThrelte()
</script>

To let Threlte do its magic, we recommend to follow our best practices for structuring your app.

The <Canvas> component provides all basic contexts in a Threlte application. The recommended app structure is to have a single child component of <Canvas> (typically named “Scene.svelte” in examples) for your Threlte app. This will allow contexts provided by useThrelte and other hooks to be used.

App.svelte
<script>
  import { Canvas } from '@threlte/core'
  import Scene from './Scene.svelte'
</script>

<Canvas>
  <Scene />
</Canvas>
Scene.svelte
<script>
  import { T, useTask } from '@threlte/core'
  import { interactivity } from '@threlte/extras'
  import Player from './Player.svelte'
  import World from './World.svelte'

  let rotation = 0

  // useTask is relying on a context provided
  // by <Canvas>. Because we are definitely *inside*
  // <Canvas>, we can safely use it.
  useTask((delta) => {
    rotation += delta
  })

  // This file is also typically the place to
  // inject plugins
  interactivity()
</script>

<T.Mesh rotation.y={rotation}>
  <T.BoxGeometry />
  <T.MeshBasicMaterial color="red" />
</T.Mesh>

<Player />
<World />

Context Not Available

The following app structure is deceiving. It looks like it should work, but it will not. The problem is that the useTask hook is called outside of the <Canvas> component, so the main Threlte context is not available. Usually hooks relying on some context will tell you with descriptive error messages when they are used outside of their context.

App.svelte
<script>
  import { Canvas, useTask, T } from '@threlte/core'

  let rotation = 0

  // This won't work, we're not inside <Canvas>
  useTask((delta) => {
    rotation += delta
  })
</script>

<Canvas>
  <T.Mesh rotation.y={rotation} />
</Canvas>