React-three-fiber: Missing or incomplete useLoader docs

Created on 13 Dec 2020  路  12Comments  路  Source: pmndrs/react-three-fiber

I've been looking for documentation regarding loaders, like useLoader or GLTFLoader, but have found next to nothing. Mostly Github issues about people not knowing how to use it..

I see that it's common to use Drei hooks instead, but I'd like to know more about what's happening.

I see a docs page for r3f, has a Loaders page,but I have no idea what it's about. Definitely doesn't seem like what I'm looking for.

I didn't find anything in the readme

Can someone who knows how Loaders in r3f actually work -please write up some docs for people like me? Maybe a readme update?

All 12 comments

that website is not ours. someone made it once. all the docs are here.

useLoader does nothing special. this is how a threejs loader works, they're async by nature:

new XYZLoader().load(url, data => console.log("got it", data))

that's a sideeffect, so in react that would be

const [data, set] = useState()
useEffect(() => void new XYZLoader().load(url, set), [url])
return data ? ... : null

useLoader abstracts the above and ties it into react suspense:

const data = useLoader(FooLoader, url)

the component will actually interrupt rendering and the loading status is managed at the parental level as it always should be. once the result is there, data is guaranteed to be available, no checking against undefined needed.

It can deal with any loader. textureloader, gltfloader, fbxloader, etc.

drei abstracts some of these to spare you from having to import those long three/examples/jsm/loaders/... urls and also sets up some of these for success. for instance it prepares gltfloader for draco, so you worry about nothing and just use it.

im german, my english is bad, but if you find a way to pack that into something very small and understandable - then let's update the docs. just watch out making it too gltf specific. useLoader just handles threejs loaders.

im german, my english is bad, but if you find a way to pack that into something very small and understandable - then let's update the docs. just watch out making it too gltf specific. useLoader just handles threejs loaders.

OK thanks. I'm taking a threejs course and building something simple with loaders in r3f. So I'll make a PR for the docs a bit later, after I understand better.

awesome! ;-)

@Seanmclem do you know if it's possible to load a Three Js scene json file into R3F. I can't find any clue on how to do it.
Right now I managed to get an Object that I exported from the Three.js editor. using Vanilla Javascript I just have to use scene.add(sceneObject) and that works, but I'm really new to R3F and I still don't know how to do this. Hopefully one day we can get a better documentation on how to use this.

@Seanmclem do you know if it's possible to load a Three Js scene json file into R3F. I can't find any clue on how to do it.
Right now I managed to get an Object that I exported from the Three.js editor. using Vanilla Javascript I just have to use scene.add(sceneObject) and that works, but I'm really new to R3F and I still don't know how to do this. Hopefully one day we can get a better documentation on how to use this.

I'll look into it. So much to learn so little time

@Seanmclem that's easily done by using primitive. It allows you to put something already existing into the scene. It is documented: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#putting-already-existing-objects-into-the-scene-graph

@drcmda I read the documentation but it is not 100% clear to me, do you have an example on how to use it? I'm fetching the scene data from a firebase database that I'm working on. I was able to get the object, how should I use . This is my code:

import React, { useState } from "react";
import { useParams } from "react-router-dom";
import { db } from "../../firebase.js";
import LoadingIcon from "./LoadingIcon";
import { Canvas } from "react-three-fiber";

const Room = () => {
  const [room, setRoom] = useState(null);
  const params = useParams();

  React.useEffect(() => {
    db.ref("/room/" + params.id)
      .once("value")
      .then((snapshot) => {
        const data = snapshot.val();
        setRoom(data);
        console.log(data);
      });
  }, []);

  return (
    <div>
      {room ? (
        <Canvas>
          <primitive object={room} position={[0, 0, 0]} />
        </Canvas>
      ) : (
        <LoadingIcon></LoadingIcon>
      )}
    </div>
  );
};

export default Room;

canvas probably shouldnt be in there if you want room to be a re-usable component. otherwise yes it's correct. primitive takes an existing object, a scene, group, any object3d.

if you have a codesandbox i can show you to make it shorter still

@drcmda Sure, here it is:

https://codesandbox.io/s/silly-wescoff-kzmkq?file=/src/App.js

As you can see, it fetches the scene object, but it won't show up.
I wonder if I'm doing something wrong, anyway, thank you for taking the time!

there were a couple of errors. youre trying to put a json object into the scene. you need to use objectloader to turn json into real threejs objects first. i used suspense here to make the loading part easier. use-asset is used by r3f for useLoader, so it's part of the bundle anyway. https://codesandbox.io/s/peaceful-visvesvaraya-q7uqr?file=/src/App.js

@drcmda wow, thank you very much! this is looking great. I'm going to study the code and learn what you did.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brandonreid picture brandonreid  路  3Comments

flxsu picture flxsu  路  4Comments

Darkensses picture Darkensses  路  6Comments

regalstreak picture regalstreak  路  5Comments

objectisundefined picture objectisundefined  路  4Comments