threlte logo
@threlte/core

useFrame

This hook is deprecated and will be removed in the next major release. Please use useTask instead. See the migration guide for more information.

This hook allows you to execute code on every frame as part of the Threlte Task Scheduling System. You receive the state (the same as useThrelte) and a clock delta in seconds. Your callback function will be invoked just before a frame is rendered. When the component unmounts it is unsubscribed automatically from the frame loop.

You may pass additional options to this hook. The property order is useful if you need to order the sequence of useFrame callbacks across the component tree where callbacks are ordered from low to high.

type ThrelteUseFrameOptions = {
  autostart?: boolean
  order?: number
  invalidate?: boolean
}

useFrame returns an object containing functions start and stop to control the execution of the callback and a store started to subscribe to its state.

Example

Starting and stopping the execution of a handler:

const { start, stop, started } = useFrame(
  () => {
    console.log('rendering…')
  },
  {
    autostart: false
  }
)

const toggleUseFrame = () => {
  if ($started) {
    stop()
  } else {
    start()
  }
}

Accessing the context and the global clocks delta inside a handler:

useFrame(({ camera }, delta) => {
  const cameraPosition = camera.current.position
})

The state available in the callback is the same as the one available with useThrelte. Some properties (such as the property camera) use a CurrentWritable store. which is a custom Threlte store. It’s a regular writable store that also has a current property which is the current value of the store. It’s useful for accessing the value of a store in a non-reactive context, such as in loops.

By default, useFrame will invalidate every frame and trigger a render after the callback is executed. You can disable this behavior by setting invalidate to false and using the function invalidate from the state to trigger a render manually.

useFrame(
  ({ invalidate }) => {
    // manually invalidate the frame
    invalidate()
  },
  {
    invalidate: false
  }
)