На момент написания этой статьи я знаю две оболочки Three.js, созданные специально для React, React-Three, которые вы можете найти здесь, и React-Three-Render, которые можно найти здесь. Но что, если вы хотите включить оригинальную и хорошо поддерживаемую библиотеку Three.js в свой проект React?

Следующее руководство позволяет вам сделать это, используя методы и ссылки жизненного цикла компонентов React, которые я объясню более подробно через секунду (шаблон, описанный ниже, не только для Three.js, он полезен для любого вида воспроизведения или анимации. в React, например Tween.js, video.js и т. д.).

Первоначально я нашел это решение на Переполнении стека. Я немного очистил код, используя стрелочные функции, без конструктора и т. Д.

import React, { Component } from 'react';
import * as THREE from 'three';
class ThreeScene extends Component{
  componentDidMount(){
    const width = this.mount.clientWidth
    const height = this.mount.clientHeight
    //ADD SCENE
    this.scene = new THREE.Scene()
    //ADD CAMERA
    this.camera = new THREE.PerspectiveCamera(
      75,
      width / height,
      0.1,
      1000
    )
    this.camera.position.z = 4
    //ADD RENDERER
    this.renderer = new THREE.WebGLRenderer({ antialias: true })
    this.renderer.setClearColor('#000000')
    this.renderer.setSize(width, height)
    this.mount.appendChild(this.renderer.domElement)
    //ADD CUBE
    const geometry = new THREE.BoxGeometry(1, 1, 1)
    const material = new THREE.MeshBasicMaterial({ color: '#433F81'     })
    this.cube = new THREE.Mesh(geometry, material)
    this.scene.add(this.cube)
this.start()
  }
componentWillUnmount(){
    this.stop()
    this.mount.removeChild(this.renderer.domElement)
  }
start = () => {
    if (!this.frameId) {
      this.frameId = requestAnimationFrame(this.animate)
    }
  }
stop = () => {
    cancelAnimationFrame(this.frameId)
  }
animate = () => {
   this.cube.rotation.x += 0.01
   this.cube.rotation.y += 0.01
   this.renderScene()
   this.frameId = window.requestAnimationFrame(this.animate)
 }
renderScene = () => {
  this.renderer.render(this.scene, this.camera)
}
render(){
    return(
      <div
        style={{ width: '400px', height: '400px' }}
        ref={(mount) => { this.mount = mount }}
      />
    )
  }
}
export default ThreeScene

Прячьте добавить или npm установите библиотеку Three.js. Продвигаясь вперед с Three, вы обнаружите, что большая часть ваших действий по устранению неполадок связана с поиском, импортом и реализацией различных библиотек для таких вещей, как элементы управления орбитой и загрузчики объектов. Эти части по-прежнему зависят от глобального загрязнения пространства имен Three.js и были бы непригодны для использования, если бы добрые души Интернета не преобразовали многие из этих библиотек в собственные модули npm и не устранили некоторые проблемы с именами. В более позднем посте я расскажу, какие из этих модулей npm, по моему мнению, работают. Между тем, три библиотеки, указанные выше, являются базовой и постоянно поддерживаются.

В приведенном выше шаблоне используются методы жизненного цикла React componentDidMount() и componentWillUnmount(). Вы будете использовать componentDidMount() для инициализации вашей сцены Three.js, вызывая сцену, средство визуализации, камеру и все остальное, что вы хотите в вашей сцене.

Обратите внимание, что средство визуализации Three.js прикреплено к элементу React с использованием ref. Согласно документации React, ссылки используются, когда «вам необходимо принудительно изменить дочерний элемент за пределами типичного потока данных». Это особенно хорошо для работы с императивной анимацией внутри React. На самом деле это единственный раз, когда я когда-либо использовал референсы, которых обычно следует избегать.

Также обратите внимание на componentWillUnmount(), где вы останавливаете анимацию и удаляете ее из DOM. Это очень важно и позволяет избежать большой утечки памяти.