can you export three.js as a component?(react)

i know components cant have use Effect by themselves so i was wondering how to rephrase this code to be used as a component for the parent app if its possible and what would the parent app look like when rephrased. I’ve looked around for examples and tutorials but the scene is always in the main parent app but i want to split up my code instead…

Heres my code:

import { useEffect } from 'react';

import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

// import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
// import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
// import { MathEx } from '@ykob/js-util';

// import Background from './background';
import fs from '../glsl/cage.fs';
import vs from '../glsl/cage.vs';
import backgroundvs from '../glsl/backgroundvs.vs'
import backgroundfs from '../glsl/backgroundfs.fs'
import handFs from'../glsl/handFs.fs'
import handVs from'../glsl/handVs.vs'
import coral from'../img//Coral_002_SD/Coraln.jpg'
import SceneInit from './lib/SceneInit';
import Content from './App.jsx'
import RadarChart from './components/radarChart';


 function CardT {
  useEffect(() => {
    const portF = new SceneInit('myThreeJsCanvas');
    portF.initialize();
    portF.animate();
    // portF.clock = new THREE.Clock()

    //
    

    let loader = new GLTFLoader();
  
    // Load a glTF resource
    loader.load('../img/cage.gltf', function (gltf) {
      const cage = gltf.scene
      const uniformData = {
        // time: {
        //   type: 'f',
        //   value: 0.0
        // },
        // colorA: { type: 'vec3', value: new THREE.Color(0xFFC000) },
        // colorB: { type: 'vec3', value: new THREE.Color(0xFFC000) }
      }
      const cageMat =  new THREE.ShaderMaterial({
        uniforms: uniformData,
        vertexShader: vs,
        fragmentShader: fs,
        wireframe: true,
        blending: THREE.NormalBlending,
        depthTest: false,
      })
      
      
      // const cageGeom = createTubeWireframe(geometry, {
      //   thickness: 0.03, // thickness in world units of tubes
      //   radiusSegments: 6, // number of segments around the tubes
      //   mode: 'quad' // face layout, use quads instead of triangles
      // });
     
      cage.scale.set(6, 6, 6)
      cage.transparent = true
      cage.traverse((o) => {
        if (o.isMesh) o.material = cageMat
      })
      portF.scene.add(cage);
    })
    
// hands
const hUniform = {
  uTime:{value:0},
  coral:{type:"t", value: new THREE.TextureLoader().load(coral)},
  iResolution:{ value: new THREE.Vector3()},
//   uRadius:{value: 0.5},
//   uTexture: {value: new THREE.TextureLoader().load(wavyTexture)}
}

async function loadmodels() {
let loader2 = new GLTFLoader()
  const [...model] = await Promise.all([
    loader2.loadAsync('./modelsGLTF/lphand/lphand.gltf'),
    loader2.loadAsync('./modelsGLTF/2hand/2hand.gltf'),
    loader2.loadAsync('./modelsGLTF/handTOPb/handTOPb.gltf'),

  ]);

  const handMat = new THREE.ShaderMaterial({
    uniforms:hUniform,
    fragmentShader:handFs,
    vertexShader:handVs,
    blending: THREE.NormalBlending,
    
  })

  const polyHand = model[0].scene
  const zHand = model[1].scene
  const hHand = model[2].scene
 
  polyHand.position.set(0,-14,-2)
  zHand.position.set(7,-14,8)
  hHand.position.set(-7,-22,8)
 
  polyHand.rotateX(3)
  polyHand.rotateY(1.1)

  zHand.rotateX(3.1)
  zHand.rotateZ(4.8)
  
  hHand.rotateX(4)
  hHand.rotateZ(2)

  polyHand.scale.set(0.25,0.25,0.25)
  zHand.scale.set(0.07,0.07,0.07)
  hHand.scale.set(1,1,1)
  
  portF.scene.add(polyHand)
  portF.scene.add(zHand)
  portF.scene.add(hHand)
  
  polyHand.traverse((h) => {
    if (h.isMesh) h.material = handMat
  })

  zHand.traverse((hb) => {
    if (hb.isMesh) hb.material = handMat
  })
  hHand.traverse((hc) => {
    if (hc.isMesh) hc.material = handMat
  })

}

loadmodels()

// particle


// bg
    const bgUniforms = {
      uTime:{value:0},
      uRadius:{value: 0.5}
  
    }
    const bgGeometry = new THREE.SphereGeometry(100);
  
    // Define Material
    const bgMaterial = new THREE.ShaderMaterial({
      vertexShader: backgroundvs,
      fragmentShader: backgroundfs,
      side: THREE.BackSide,
      uniforms: bgUniforms,
      depthTest: false
    });
    const bg = new THREE.Mesh(bgGeometry, bgMaterial)
    portF.scene.add(bg)

// bg2
const otAo = new THREE.TextureLoader().load('../img/fP/futuristic-p-ao.png')
otAo.wrapS = THREE.RepeatWrapping;
otAo.wrapT = THREE.RepeatWrapping;
otAo.repeat.set( 3, 3 );
const otGeo = new THREE.SphereGeometry(120,120);
const otMat = new THREE.MeshPhysicalMaterial({
  // color:0xf08080,
  // emissive:0x00eeff,
  emissiveIntensity: 0.4,
  clearcoatMap:otAo,
  // displacementMap:otDis,
  side:THREE.DoubleSide,
  roughness:0,
  metalness:0,
  transmission:1,
  transmissionMap:otAo,
  clearcoat:1,
  ior:1,
})
const otbg = new THREE.Mesh(otGeo,otMat)
portF.scene.add(otbg)

// card
  const texture1 = new THREE.TextureLoader().load('../img/joshcoin3small.png')
	const texture2 = new THREE.TextureLoader().load('../img/joshcoin3small2.jpg')
	const cardgeoFront = new THREE.PlaneGeometry(6, 8);
	const cardgeoBack = new THREE.PlaneGeometry(6, 8);
	const mat1 = new THREE.MeshBasicMaterial({
		map: texture1
	})
	const mat2 = new THREE.MeshBasicMaterial({
		map: texture2,
		side: THREE.BackSide
	})
	const fcard = new THREE.Mesh(cardgeoFront, mat1);
	const bcard = new THREE.Mesh(cardgeoBack, mat2);

	const card = new THREE.Group();
	card.add(fcard);
	card.add(bcard);

	portF.scene.add(card);


	card.rotateZ(0.4)

    

    const animate = () => {
      hUniform.uTime.value = (portF.clock.getElapsedTime())
      portF.onWindowResize()
      requestAnimationFrame(animate);
    };
    animate();
  }, []);


  return (
    <div>
      <canvas id="myThreeJsCanvas" />
    </div>
   
  );
  
}

export default CardT;

Im relatively new to three.js and react so sorry for any obvious errors

Yes, you can use React-three-fiber and react-three/drei

1 Like

yhh fairs that sounds like a good starting point do you know how i could rephrase what i already have with that or know of any resources to get me started? Most of my three.js knowledge started of from using vanilla js thats why my code looks like what it looks like at the moment

It wouldn’t make sense to use three in react like that precisely because you loose integration. Use fiber and you will be alle to share components. Fiber is not a wrapper but a renderer just like react-dom

1 Like

ok do you have any examples? i can give that a try how would i share what i have and what would that look like for me with my project using fibre as the renderer

first have a look into how to load a gltf model with useGLTF, this should give an idea of the structure…

1 Like

thnx ill give it a try is traversing a model pretty similar syntax wise btw or is it very different?

that’s a question more for @drcmda tbh, apparently traversing is “bad practice” in r3f you’d use something like gltfjsx to make a list of parts in the model and change each of the parts individually, it’s longer in my opinion and can be buggy in terms of position precision if you have small models…

kl cheers ill do some more research on it too also sorry too drag on but when i try to load up some boiler plate code i keep getting this error have you seen this before?

Could not resolve “react-native/Libraries/Pressability/Pressability”

node_modules/@react-three/fiber/native/dist/react-three-fiber-native.esm.js:9:25:
  9 │ ...bility from 'react-native/Libraries/Pressability/Pressability';
    ╵                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It says i should mark the path “react-native/Libraries/Pressability/Pressability”
as external to exclude it from the bundle, which will remove this error.

But i honestly dont know how to do that… :smiling_face_with_tear:

i’ve got no idea about react native sadly :expressionless:

1 Like

no problems cheers dude for the advice :+1:

this is a program structure question, not a componentization question

yh i should’ve included that more explicitly in the header as well but i didn’t know anything about react three fibre its also its my first react project (all i know is vanilla js) so anything and everything is helping at the moment if you have any suggestion or recommendations for resources program structure im all ears and would be much appreciated tbf :sweat_smile:

ESM or Class should be helpful for function collections

1 Like

ohh ok into one big constructor class like the one below?

class Car {
  constructor(name, year) {
    this.name = name;
    this.year = year;
  }
}
or this?
export class C extends Super {
  method() {
    console.log('method');
  }
}

and that would have a bunch of functions or would i split them into files too?

kind of… the structure for extending a class is slightly different

export class Car extends Vehicle{
  constructor(name, year) {

    super() // invokes the original class "Vehicle"

    this.name = name;
    this.year = year;
 
    //methods can be declared either here
    this.changeCarColor = () =>{

    }

  }
  
  // or methods can be declared here... both invoked with car.[methodName]()
  moveCarForward(){

  }

}
1 Like

thnx ill give it a little more research and a try

i think you need more familiarity with react in that case. the only feasible option you have to do what you want is fiber, and it works both for vanilla threejs on the web and react-native where threejs doesn’t run in a webview but in a native openGLES context.

vanilla threejs doesn’t run on native platforms otherwise, and you sure wouldn’t want it to run in an embed browser. and even if you do that, threejs is imperative oop, the polar opposite of react. a component happens in a level above, it is a different paradigm.

i would start with basics, get a react native project running that has a spinning box or something like that, click this link React Three Fiber Documentation

and after you have that, exporting a component is trivial. especially with gltfjsx where the scene of the model is JSX that you can bind to state.

1 Like

yh fairs don’t worry i started on the react three drei scene as soon as it was suggested tbf i have done the lights and have converted my gtlfs to gtlfjsx, as well as have my starting shape the hardest part for me so far is translating smaller more more specific things that i already had to do extensive research on the initial scene above before like mapping a textures on 2 both sides of a sided plane or applying shaders and uniforms to gtlfs. I’ve just been assessing and and trying out all the suggestions here in case theres a quicker way to use what i’ve already created and save time

react-three-fiber is a good solution,but I prefer to encapsulate functions and animations myself,easier to control details and bugs,you can also assemble your favorite third-party classes