Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sanchedev/tiny-engine/llms.txt

Use this file to discover all available pages before exploring further.

createContext and useContext let you share a value with all descendant components in a scene-graph subtree without passing props manually through every layer. createContext produces a context object that includes a Provider JSX component; any component rendered inside that Provider can call useContext to read the provided value.

createContext

Signature

createContext<T>(defaultValue: T): ContextCreated<T>

Parameters

defaultValue
T
required
The fallback value returned by useContext when no matching Provider is found above the component in the scene graph.

Return value

A ContextCreated<T> object with two members:
MemberDescription
ProviderA JSX component that accepts a value prop and a children prop. Wrap any subtree with it to inject the provided value.
defaultValueThe default value supplied to createContext.

useContext

Signature

useContext<T>(contextCreated: ContextCreated<T>): T

Parameters

contextCreated
ContextCreated<T>
required
The context object returned by createContext. Pass the same reference that was used to create the Provider.

Return value

T — the value from the nearest Provider ancestor in the scene graph, or defaultValue if no provider is found.

Example — score context shared across components

GameScene.tsx
import { createContext, useContext, useSignal } from 'tiny-engine/hooks'

// 1. Create the context at module scope
interface GameState {
  score: () => number
  addScore: (n: number) => void
}

const GameCtx = createContext<GameState>({
  score: () => 0,
  addScore: () => {},
})

// 2. Provide it at the top of your scene
function GameScene() {
  const [score, setScore] = useSignal(0)

  const state: GameState = {
    score,                        // getter — reactive
    addScore: (n) => setScore(score() + n),
  }

  return (
    <GameCtx.Provider value={state}>
      <transform>
        <Player />
        <HUD />
      </transform>
    </GameCtx.Provider>
  )
}

// 3. Consume anywhere in the subtree
function Player() {
  const { addScore } = useContext(GameCtx)

  const collider = useRefNode(PrimaryNode.Collider)

  useEvent(collider, 'colliderEntered', (other) => {
    if (other.group.has('coin')) {
      addScore(10)
    }
  })

  return (
    <transform>
      <collider
        ref={collider}
        shape={shapes.circle(12)}
        group={['player']}
        collidesWith={['coin']}
      />
      <sprite textureId={PLAYER_TEXTURE} />
    </transform>
  )
}

function HUD() {
  const { score } = useContext(GameCtx)

  return (
    <transform>
      {/* score is a SignalGetter — reactive prop */}
      <text text={() => `Score: ${score()}`} />
    </transform>
  )
}

Example — theme / palette context

ThemeScene.tsx
import { createContext, useContext } from 'tiny-engine/hooks'

const ThemeCtx = createContext<'light' | 'dark'>('light')

function App() {
  return (
    <ThemeCtx.Provider value="dark">
      <Card />
    </ThemeCtx.Provider>
  )
}

function Card() {
  const theme = useContext(ThemeCtx)
  const bgTexture = theme === 'dark' ? DARK_CARD : LIGHT_CARD

  return <sprite textureId={bgTexture} />
}
Context values are not reactive by themselves. If you change the value prop on a Provider, components that already consumed the context will not re-render automatically. To propagate updates reactively, store a SignalGetter (or an object containing signal getters) inside the context value, as shown in the GameScene example above. Consumers then call score() in a reactive position — a JSX prop or useEffect — to track changes.
Define context objects at module scope (outside any component) so that the same reference is shared across all usages. Creating a new context inside a component function will produce a different context object on every render, making useContext unable to find the matching provider.

Build docs developers (and LLMs) love