Textures, models, audio — three.js ships a loader class for each kind.
solid-three exposes two ways to use them that both plug into Solid's
<Suspense> so the rest of the scene keeps rendering while the asset is
fetching.
useLoader: the hook
useLoader(loaderClass, url) returns an
Accessor that resolves to the
loaded asset. Wrap the consumer in a <Suspense> so Solid knows what to
do while it's pending.
A cube with a random photo from picsum.photos mapped onto every face.
While the image is loading, <Suspense> shows nothing (you can give it a
fallback if you want a placeholder).
useLoader caches by URL across the whole app, so two components
asking for the same texture share one load and one GPU upload. The
LoaderCache is configurable per call
when you need different scoping.
Resource: the component
The declarative version. <Resource loader={...} url="..."> does the same
fetching, but you write it as JSX inside the scene tree. When the
attachment is obvious — a TextureLoader result going into .map of the
parent material — attach does the wiring for you.
Same outcome, different shape. Use whichever reads better in context:
useLoaderwhen you need the value as a Solid signal — to derive other signals from it, pass it to a function, or do something programmatic.<Resource>when you just want to drop a loaded asset into the tree and forget about it.
Both forms return Solid resources, so the usual reactivity rules apply:
read them inside createMemo/createEffect to track loading state,
or inside <Suspense> to render a fallback. Cache behaviour, base URLs,
array/record URL shapes, error handling — see
useLoader for the full surface.
That's the everyday tree: components, props, signals, events, frames, loaders. The next chapter is a deliberate break from the mapping — a way to send children somewhere other than where their JSX would suggest.
Last updated: 6/8/26, 11:20 AM