OBJ-loader does not load file with dynamic path via String input

Hi guys,

why does this work:

function Scene() {
  
    const obj = useLoader(OBJLoader, require("../obj-files/H17999_67.obj")); 

    return <primitive object={obj} scale={0.02} />
}

But the following does not:

function Scene() {

    const objPath = "../obj-files/H17999_67.obj";

    const obj = useLoader(OBJLoader, require(objPath)); 

    return <primitive object={obj} scale={0.02} />

}

error: cannot find module

For my app I need to be able to load the path dynamically based on a String

Thanks!

require() isn’t a browser feature, so probably that’s something your bundler is resolving at compile time and replacing in the compiled code. Hard to say exactly without running the build step locally to see what your output is, you may need to share those details to get a better answer here.

You could replace that with dynamic import(), not require().

const objContent = await import('../obj-files/H17999_67.obj');
const obj = useLoader(OBJLoader, objContent);

Or you can put the model in a static folder. Then pass a path — relative to the page, not the javascript source file — directly to useLoader. This is what probably 99% of three.js apps do, rather than asking your build process to resolve imports of 3D models, just put the model in a static folder and fetch it from the frontend without import() or require().

Thank you, Don. Unfortunately this was not successful.

I amended the code to:

async function Scene() {

    // eslint-disable-next-line
    const objPath = "../obj-files/H17999_67.obj";

    // eslint-disable-next-line
    const objContent = (await import(objPath))
    const obj = useLoader(OBJLoader, objContent);

    //const obj = useLoader(OBJLoader, require(objPath)); 
    console.log(obj);

    // eslint-disable-next-line
    return <primitive object={obj} scale={0.02} />

}

But I get the following error:

Uncaught runtime errors:
×
ERROR
Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
at throwOnInvalidObjectType (alhost:3000/static/js/bundle.js:126214:13)
at reconcileChildFibers (calhost:3000/static/js/bundle.js:127000:11)
at reconcileChildren (calhost:3000/static/js/bundle.js:130915:32)
at mountIndeterminateComponent (alhost:3000/static/js/bundle.js:131768:9)
at beginWork (ost:3000/static/js/bundle.js:132993:20)
at HTMLUnknownElement.callCallback (calhost:3000/static/js/bundle.js:133300:18)
at Object.invokeGuardedCallbackDev (alhost:3000/static/js/bundle.js:133344:20)
at invokeGuardedCallback (ost:3000/static/js/bundle.js:133398:35)
at beginWork$1 (host:3000/static/js/bundle.js:137821:11)
at performUnitOfWork (ocalhost:3000/static/js/bundle.js:137108:16)

I also tried a few other things which did not work. What would be needed to understand the problem better?

A static folder probably wouldnt work as most of the files will be only made available during runtime.

thanks

What is the ESLint error you’ve disabled above the import?

The recommended way to do this is shown at React Three Fiber Documentation — there is no import or require. If you’ve decided against using that documentation already, it might help if you could share why.

A static folder probably wouldnt work as most of the files will be only made available during runtime.

This doesn’t make sense to me, sorry! A bundler packages up your JS source code and puts it into a static folder. When using require() — which doesn’t exist in the web runtime — you’re asking the bundler to do the same for 3D models, replacing the require() during build, which bundlers often cannot do without special configuration. Instead you can just put the 3D model directly into a static folder, so the bundler doesn’t have to deal with it, unless you’re doing something very unusual.

What would be needed to understand the problem better?

Ideally a minimal, reproducible example.