# Texture don't load on first render, using either useTexture or TextureLoader (with repros)

**URL:** <https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849>\
**Category:** Questions\
**Tags:** loaders, materials, textures\
**Created:** [March 8, 2023, 4:30pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849 "2023-03-08T16:30:54Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 8, 2023, 4:30pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/1 "2023-03-08T16:30:54Z")

</div>

Hi,

I’m working on a small project where I load textures dynamically from a server on the first load and user actions. Everything works fine, except for the first render.

I created a repro here: [immutable-wave-cprcpd - CodeSandbox](https://codesandbox.io/p/sandbox/immutable-wave-cprcpd?file=%2Fsrc%2FApp.jsx)

Simply click on the canvas to see the issue.

For some reason, it seems the texture update is queued but never rendered. Resizing the browser window or scrolling makes it render correctly. I can also see for a very short time the initial texture being applied right before the new texture when switching textures.

Not sure what I’m doing wrong here?

Thanks!

---

<div class="post-metadata">

**Author:** ![Lawrence3DPK](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/lawrence3dpk/32/29184_2.png) [@Lawrence3DPK](https://discourse.threejs.org/u/Lawrence3DPK)\
**Post date:** [March 8, 2023, 5:14pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/2 "2023-03-08T17:14:39Z")

</div>

`useLayoutEffect` is a version of [`useEffect`](https://beta.reactjs.org/reference/react/useEffect) that fires before the browser repaints the screen. the result of `TextureLoader` is only returned after the texture has been loaded meaning you’ve got a race condition eg. the screen is being rendered before the texture has loaded, have you considered using `useTexture` from within drei?

[https://drei.pmnd.rs/?path=/story/loaders-texture--use-texture-scene-st](https://drei.pmnd.rs/?path=/story/loaders-texture--use-texture-scene-st)

---

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 8, 2023, 5:16pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/3 "2023-03-08T17:16:26Z")

</div>

Thanks for your answer!

I tried using `useEffect` as well without much success.

My first version was using `useTexture` but I had some weird issues with the bumpMap or normalMap not being applied correctly. I can do a repro as well.

---

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 8, 2023, 6:53pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/4 "2023-03-08T18:53:27Z")

</div>

I unfortunately have the exact same issue with `useTexture` as shown here: [great-margulis-enrzyy - CodeSandbox](https://codesandbox.io/p/sandbox/great-margulis-enrzyy?file=%252Fsrc%252FApp.jsx)

You can also see the issue I encountered with normal maps (or any kind of maps). Compare this to the first codesandbox. The front part is much darker and you can see strong edges on the shoulders. This does not happen when using the TextureLoader. (I know the code to set the new texture is wrong in this case, but since the initial texture has the normal map I just need to change a prop to trigger the rerender to show the issue)

---

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 9, 2023, 10:57pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/5 "2023-03-09T22:57:13Z")

</div>

Would appreciate any pointers on this, tried multiple examples in the documentation and GitHub issues (like here: [Textures from `useTexture` don’t receive options applied in `useEffect` · Issue #902 · pmndrs/drei · GitHub](https://github.com/pmndrs/drei/issues/902#issuecomment-1264720263)) but I can’t get rid of the problem.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [March 9, 2023, 11:09pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/6 "2023-03-09T23:09:48Z")

</div>

useTexture is nothing else than new THREE.TextureLoader().load(url, data =\> … it cannot have an effect on normals etc. you should always prefer useTexture though because it prevents jank, it will pre-emptively upload the texture to the gpu. ootb threejs will only start to upload once the renderer “sees” a texture, if it’s in frustum.

a normal texture can behave messed up, in threejs, if it has the from color space (it should be linear), and three expects textures to be upside down (flipY=false)

other than that the sandbox i just tried makes no sense to me, it has a useLayoutEffect with async texture loaders in it (that means the results will be ready … whenever). that completely drowns what useLoader does, it destroys suspense, so the results is practically a race condition and cannot be awaited any longer. if you have changed it to useTexture let’s have another look.

```jsx
const textures = useTexture({
  map: "foo,png",
  bumpMap.: "bar.png",
  ...
})
return (
  <mesh>
    <meshStandardMaterial {...material} />

```

another thing is `material={materialRef.current}` you can’t put one ref on multiple materials. a ref is a reference to a single object.

---

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 9, 2023, 11:15pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/7 "2023-03-09T23:15:20Z")

</div>

Thanks for your answer. I did make a second sandbox with useTexture that you can try here: [great-margulis-enrzyy - CodeSandbox](https://codesandbox.io/p/sandbox/great-margulis-enrzyy?file=%252Fsrc%252FApp.jsx)

I’m using the callback from useTexture but I also tried with the just settings the map props right after or in a useEffect without success

---

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 9, 2023, 11:18pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/8 "2023-03-09T23:18:04Z")

</div>

I’m not sure I understand the part about the ref. My ref references one material and I use the referenced material on multiple meshes.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [March 9, 2023, 11:19pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/9 "2023-03-09T23:19:31Z")

</div>

why does the group have a material? only meshes can have materials? i don’t understand what is supposed to happen.

there are also meshes without any material.

---

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 9, 2023, 11:21pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/10 "2023-03-09T23:21:56Z")

</div>

I’ve read that this was the way to share a single material between multiple meshes. Those answer might have been wrong.

The mesh without material are the buttons. I just removed it to make the repro simpler. I just removed the mesh, it’s not needed for my example.

---

<div class="post-metadata">

**Author:** ![drcmda](https://avatars.discourse-cdn.com/v4/letter/d/91b2a8/32.png) [@drcmda](https://discourse.threejs.org/u/drcmda)\
**Post date:** [March 9, 2023, 11:25pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/11 "2023-03-09T23:25:31Z")

</div>

```jsx
  const [texture1, texture2, .......] = useTexture(urls)
  const material = useMemo(() => {
    texture1.repeat.set(x, y)
    ...
    return new THREE.StandardMaterial({ ........ })
  }, [texture])
  return (
    <group>
     <mesh geometry={foo} material={material} />
     <mesh geometry={bar} material={material} />
     <mesh geometry={baz} material={material} />
```

---

<div class="post-metadata">

**Author:** ![moimael](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/moimael/32/34213_2.png) [@moimael](https://discourse.threejs.org/u/moimael)\
**Post date:** [March 9, 2023, 11:30pm UTC](https://discourse.threejs.org/t/texture-dont-load-on-first-render-using-either-usetexture-or-textureloader-with-repros/48849/12 "2023-03-09T23:30:36Z")

</div>

That was it!

Many thanks for taking the time. Truly appreciate it!
