React-three-fiber: Initial teething issues

Created on 11 Oct 2020  路  5Comments  路  Source: pmndrs/react-three-fiber

Hi there, firstly I'd like to say this lib (and partner libs) look awesome. As a long-time React developer looking to get into some 3D/physics stuff, this seems like a great place for me to be.

I'm not sure if this is a bug report, but more a couple of teething issues I've just experienced getting a simple project setup and running some code from the readme (pasted below).

When I first installed the latest version of react-three-fiber (5.0.3) I was warned that use-asset (a dependency of this lib) relied on v4, so I installed v4 (4.2.21). And after fixing a few things in the example code I had a running app, but nothing rendered. At this point I had no warnings about version clashes, but nothing worked. Is v4 broken, or perhaps a clash with one of my other dependencies?

I decided to try installing the latest version again and despite the warning everything rendered as expected. I assume that https://github.com/pmndrs/use-asset just needs a looser dependency? Though it's a bit weird for library A to depend on library B, which in turns depends on library A. Not really sure what the best approach is here.

Here's the other (relevant seeming) dependencies I had installed when nothing was rendering:

Note: I was not actually using use-cannon for anything at this point.

{
  "react": "^16.13.1",
  "react-dom": "^16.13.1",
  "react-three-fiber": "^4.2.21",
  "three": "^0.119.1",
  "typescript": "^4.0.3",
  "use-cannon": "^0.5.3"
}

Another couple of issues I had initially were (and I'm happy to open a PR to fix):

  1. Warnings about unused variables - specifically the e in handlers (it's a pretty common linting/typescript setting)
  2. Typescript warning about accessing mesh.current.rotation as the ref won't be populated to begin with
  3. Confusion about what to type (typescript) the props for the Box component

As for the types I've settled on JSX.IntrinsicElements['mesh'], but I'm not sure if this is correct. Is this what is intended or is there a nicer way to access these?

How would you feel about having typescript examples in the readme?

I understand that v5 is very new and that'd probably explain the dependency issues, and that keeping documentation in a readme (without linting etc) is difficult. I've had plenty of times myself that code examples in my documentation didn't work.

I'm very happy to help with any of the above issues. 馃檪 And apologise if this isn't the right place to post them.

import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from 'react-three-fiber'

function Box(props) {
  // This reference will give us direct access to the mesh
  const mesh = useRef()

  // Set up state for the hovered and active state
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)

  // Rotate mesh every frame, this is outside of React without overhead
  useFrame(() => (mesh.current.rotation.x = mesh.current.rotation.y += 0.01))

  return (
    <mesh
      {...props}
      ref={mesh}
      scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
      onClick={(e) => setActive(!active)}
      onPointerOver={(e) => setHover(true)}
      onPointerOut={(e) => setHover(false)}
    >
      <boxBufferGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

ReactDOM.render(
  <Canvas>
    <ambientLight />
    <pointLight position={[10, 10, 10]} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>,
  document.getElementById('root')
)

Most helpful comment

I'm glad it's not just me. 馃槀

If you wanted all the types you could also use ReactThreeFiber.Object3DNode<THREE.Mesh, typeof THREE.Mesh>, but that's even more wordy.

Would be nice to get some readable aliases for these e.g. MeshProps. 馃槉

All 5 comments

As for the types I've settled on JSX.IntrinsicElements['mesh'], but I'm not sure if this is correct.

I recently needed to figure this out, too. Here's where I landed:

import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, ReactThreeFiber, useFrame } from 'react-three-fiber'
import { Mesh } from 'three'

function Box(props: { position: ReactThreeFiber.Vector3 }) {
  // This reference will give us direct access to the mesh
  const meshRef = useRef<Mesh>()

  // Set up state for the hovered and active state
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)

  // Rotate mesh every frame, this is outside of React without overhead
  useFrame(() => {
    if (meshRef.current?.rotation) {
      meshRef.current.rotation.x = meshRef.current.rotation.y += 0.01
    }
  })

  return (
    <mesh
      {...props}
      ref={meshRef}
      scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
      onClick={(e) => setActive(!active)}
      onPointerOver={(e) => setHover(true)}
      onPointerOut={(e) => setHover(false)}
    >
      <boxBufferGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

ReactDOM.render(
  <Canvas>
    <ambientLight />
    <pointLight position={[10, 10, 10]} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>,
  document.getElementById('root')
)

I'm glad it's not just me. 馃槀

If you wanted all the types you could also use ReactThreeFiber.Object3DNode<THREE.Mesh, typeof THREE.Mesh>, but that's even more wordy.

Would be nice to get some readable aliases for these e.g. MeshProps. 馃槉

I just found this repo and you issue is the first thing I went looking for
Here is how I did.

import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, ReactThreeFiber, useFrame } from 'react-three-fiber'
import THREE, { Object3D } from 'three'

type MeshProps = ReactThreeFiber.Object3DNode<THREE.Mesh, typeof THREE.Mesh>

function Box(props: MeshProps) {
    // This reference will give us direct access to the mesh
    const mesh = useRef<Object3D>()

    // Set up state for the hovered and active state
    const [hovered, setHover] = useState(false)
    const [active, setActive] = useState(false)

    // Rotate mesh every frame, this is outside of React without overhead
    useFrame(() => {
        if (!mesh.current) return
        mesh.current.rotation.x = mesh.current.rotation.y += 0.01
    })

    return (
        <mesh
            {...props}
            ref={mesh}
            scale={active ? [1.5, 1.5, 1.5] : [1, 1, 1]}
            onClick={(_e) => setActive(!active)}
            onPointerOver={(_e) => setHover(true)}
            onPointerOut={(_e) => setHover(false)}
        >
            <boxBufferGeometry args={[1, 1, 1]} />
            <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
        </mesh>
    )
}
ReactDOM.render(
    <Canvas>
        <ambientLight />
        <pointLight position={[10, 10, 10]} />
        <Box position={[-1.2, 0, 0]} />
        <Box position={[1.2, 0, 0]} />
    </Canvas>,
    document.getElementById('root'),
)

As mentioned in https://github.com/pmndrs/react-three-fiber/issues/11#issuecomment-675318049, Object3D appears to be the way to go indeed.

all things typescript are by contribution. i myself have no idea whatsoever what these crazy long type defs even mean. makes it worse that threejs doesn't want offcial TS support, so their types are crude at best. if you see something obvious please make prs. with plain vanilla js you can np, install this lib and use the example just like that. you could add a ts example, but please do it in a collapsed expander.

Was this page helpful?
0 / 5 - 0 ratings