Mesh, Geometry, Material
See how an imperative mesh setup becomes nested JSX with constructor args and material props.
React Three Fiber Three.js
Pinned example stack
react@19.1.1react-dom@19.1.1@react-three/fiber@9.3.0three@0.180.0
Exact Conversion
Switch between the React Three Fiber and Three.js examples, then test the R3F result in the live preview below.
import { Canvas } from '@react-three/fiber';
function HeroSphere() { return ( <mesh> <sphereGeometry args={[1, 32, 16]} /> <meshStandardMaterial color="#f97316" metalness={0.2} roughness={0.25} /> </mesh> );}
export default function App() { return ( <div style={{ height: '100vh', background: '#0f172a' }}> <Canvas camera={{ fov: 50, position: [0, 0.6, 4] }} dpr={[1, 2]}> <color attach="background" args={['#0f172a']} /> <ambientLight intensity={0.35} /> <directionalLight position={[2, 3, 4]} intensity={1.6} /> <HeroSphere /> </Canvas> </div> );}import * as THREE from 'three';
const scene = new THREE.Scene();scene.background = new THREE.Color('#0f172a');
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 100);camera.position.set(0, 0.6, 4);
const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));renderer.setSize(window.innerWidth, window.innerHeight);document.body.style.margin = '0';document.body.appendChild(renderer.domElement);
const ambientLight = new THREE.AmbientLight('#ffffff', 0.35);const directionalLight = new THREE.DirectionalLight('#ffffff', 1.6);directionalLight.position.set(2, 3, 4);
const geometry = new THREE.SphereGeometry(1, 32, 16);const material = new THREE.MeshStandardMaterial({ color: '#f97316', metalness: 0.2, roughness: 0.25,});const sphere = new THREE.Mesh(geometry, material);
scene.add(ambientLight, directionalLight, sphere);
function onResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight);}
window.addEventListener('resize', onResize);renderer.render(scene, camera);Live preview
What Changed
new THREE.Mesh(geometry, material)becomes a<mesh>with geometry and material children.- Constructor arguments move into
args. - Material option objects become regular JSX props like
color,metalness, androughness. - The scene still needs light because
meshStandardMaterialbehaves the same in both APIs.
The Big Idea
Section titled “The Big Idea”The geometry and material are not “special React children.” They are still the same underlying Three.js objects. R3F just lets you express the ownership structure directly in the markup instead of building the hierarchy in separate variables.