---
title: Holding a frame
description: Hold a frame while a texture, font or shader loads, and carry the frame context into another React reconciler.
---

Hosts and renderers draw synchronously, but some of what they draw arrives later: a texture,
a font, a shader compile. `useHold(label, when)` from `@motionactor/renderers/react` holds the
frame while `when` is true, and the host waits for it before showing or capturing the frame:

```tsx twoslash title="texture.tsx"
// @jsx: react-jsx
// ---cut---
import { useEffect, useState } from "react";
import { useHold } from "@motionactor/renderers/react";

export function useTexture(url: string) {
  const [bitmap, setBitmap] = useState<ImageBitmap | null>(null);
  useHold(`texture ${url}`, bitmap === null);
  useEffect(() => {
    let live = true;
    void fetch(url)
      .then((response) => response.blob())
      .then(createImageBitmap)
      .then((next) => live && setBitmap(next));
    return () => {
      live = false;
    };
  }, [url]);
  return bitmap;
}
```

The label is what a capture timeout reports, so name the thing being waited for.

## Another React tree

The frame source and the gate reach components through React context. A surface with its own
React reconciler, such as a React Three Fiber or a Skia canvas, starts a new tree where that
context is gone. Read both outside the canvas and bind them again inside it:

```tsx twoslash title="canvas-host.tsx"
// @jsx: react-jsx
import type { ReactNode } from "react";
declare function Canvas(props: { children: ReactNode }): ReactNode;
// ---cut---
import {
  FrameGateBinding,
  FrameSourceBinding,
  useFrameGate,
  useFrameSource,
} from "@motionactor/renderers/react";

function CanvasHost({ children }: { children: ReactNode }) {
  const source = useFrameSource();
  const gate = useFrameGate();
  return (
    <Canvas>
      <FrameSourceBinding source={source}>
        <FrameGateBinding gate={gate}>{children}</FrameGateBinding>
      </FrameSourceBinding>
    </Canvas>
  );
}
```

The Three.js and Skia backends both do this.
